题注:道生一,一生二,二生三,三生万物
一:关注于注册中心
1.什么是consul?能做什么?有哪些替代品及比较?
consul:服务治理:注册中心,专注于服务注册与发现,服务健康检查,K/V,多数据中心
常见替代品:Zookeeper,Eureka
consul 逐渐会成为主流
2.consul 中的组件
agent分为server和client模式,均为集群中的一员,集群中不可缺少server,一般3或5个agent做server,可任意多个client(也可以无client) ;server之间实现【分布式一致性】,client可以注册service和check(可看做是consul的代理)
不需要为客户端client配置服务器的地址; 发现是自动完成的(Agent注册到集群相当简单)。 其次,检测节点故障的工作不是放在服务器上,而是分布式的。
(节点注册的服务有限,但是如果一个client节点注册了过多的服务,则这个节点的风险很大--》建议服务网格Service mesh的方式)
3.安装配置
方式很多且简单:单机,集群,单机伪集群,docker集群
单机伪集群: http://www.imooc.com/article/277290
官方docker集群: https://github.com/hashicorp/consul/blob/master/demo/docker-compose-cluster/docker-compose.yml
建议使用集群模式保证高可用性
注意:单机和集群还有一点不同的是:
/v1/agent/services VS /v1/catalog/services
agent:代表本节点;catalog:代表consul整体目录
以目录方式思考consul的实体模型
service包含Node信息,代表注册该service的节点
4.生命周期(关注节点及代理的情况)
Consul集群中的每个Agent都经历一个生命周期。了解此生命周期对于构建Agent与集群交互的心智模型以及集群如何处理节点非常有用。
当Agent首次启动时,它不知道集群中的任何其他节点。要发现它的同行,它必须加入集群。这是通过join命令或通过提供正确的配置来启动时自动加入来完成的。一旦一个节点加入,这个信息就会传递给整个集群,这意味着所有节点最终都会意识到对方。 如果agent是server,则现有server将开始复制到新节点。
在网络出现故障的情况下,某些节点可能无法被其他节点访问。在这种情况下,无法访问的节点被标记为失败。不可能区分网络故障和Agent崩溃,所以两种情况都是一样的。一旦节点被标记为失败,这个信息在服务目录中被更新。
注意:这里有一些细微差别,因为只有当Server仍然可以形成quorum时才可以进行更新。 网络恢复或崩溃的Agent重新启动后,集群将自行修复,并将节点取消标记为失败。目录中的健康检查也将更新以反映这一点
当一个节点离开时,它指定了它的意图,并且集群将该节点标记为已经离开。与失败的情况不同,节点提供的所有服务都立即取消注册。如果代理是Server,则复制到该Server将停止。
为了防止死亡节点(处于失败或者离开状态的节点)的累积,Consul将自动从目录中移除死亡节点。这个过程被称为收割。这目前是在72小时的可配置间隔内完成的(改变收割间隔由于在停电情况下的后果而不被推荐)。收割类似于离开,导致所有关联的服务被注销。
Http API方式注册service
配置文件形式注册service
5.Consul Http API
常用API
agent: 返回本代理的相关实体
/v1/agent/checks : 返回本地agent注册的所有检查(包括配置文件和HTTP接口)
/v1/agent/services : 返回本地agent注册的所有 服务
/v1/agent/members : 返回agent在集群的gossip pool中看到的成员
/v1/agent/self : 返回本地agent的配置和成员信息
/v1/agent/join/ : 触发本地agent加入node
/v1/agent/force-leave/>: 强制删除node
/v1/agent/check/register : 在本地agent增加一个检查项,使用PUT方法传输一个json格式的数据
/v1/agent/check/deregister/ : 注销一个本地agent的检查项
/v1/agent/check/pass/ : 设置一个本地检查项的状态为passing
/v1/agent/check/warn/ : 设置一个本地检查项的状态为warning
/v1/agent/check/fail/ : 设置一个本地检查项的状态为critical
/v1/agent/service/register : 在本地agent增加一个新的服务项,使用PUT方法传输一个json格式的数据
/v1/agent/service/deregister/ : 注销一个本地agent的服务项
catalog:返回整个consul管理的相关实体(不包含check)
(每一个Client Agent 可以通过catalog获取Consul集群中其它Agent上注册的相关服务信息)
/v1/catalog/register : Registers a new node, service, or check
/v1/catalog/deregister : Deregisters a node, service, or check
/v1/catalog/datacenters : Lists known datacenters
/v1/catalog/nodes : Lists nodes in a given DC
/v1/catalog/services : Lists services in a given DC
/v1/catalog/service/ : Lists the nodes in a given service(CatalogService)
/v1/catalog/node/ : Lists the services provided by a node
(CatalogNode)
health check相关
(list check for node)
/v1/health/node/: 返回node所定义的检查,可用参数?dc=
(list check for service)
/v1/health/checks/: 返回和服务相关联的检查,可用参数?dc
(list node for service 含check信息)
/v1/health/service/: 返回给定datacenter中给定node中service
(list check for state)
/v1/health/state/: 返回给定datacenter中指定状态的服务,state可以是"any", "unknown", "passing", "warning", or "critical",可用参数?dc=
参考:https://www.jianshu.com/p/c8558ad302b1
6.健康检查(服务节点是否可用--最简单的)
对于Agent来说:健康检查一般就是服务是否可用的检查,测试的方式是请求服务的一个uri,看返回结果
健康检查一般使用Actuator (监控SpringBoot微服务的利器)来做
服务配置健康检查的uri,且actuator可以提供自定义的检查
可以无侵入的注册check
定义一个脚本,check注册该脚本,检查时执行该脚本,根据脚本返回确定是否健康
参考:https://www.cnblogs.com/duanxz/p/9662862.html
7.Service Discovery VS Service Mesh
集中式 VS 分布式
service discovery:注册中心维护一个注册表,服务注册于注册表,服务发现查询注册表获取服务(头脑模型)
service mesh :每个服务都有一个代理与之交互,代理之间互相连接达到微服务互联互调;代理可以看做是服务之上的一层中间层(头脑模型)
服务绑定代理,且服务无感知。
服务注册多使用Agent:每个Consul Agent维护自己的一套服务和检查注册以及健康信息
服务发现多使用Catalog:该目录(Catalog)用于通过Consul提供的各种接口公开这些信息
Consul 集群搭建及后续的扩容方案(join)(注册Agent)
8.Conusl使用模式:最常使用的是1,3
1.consul的官方推荐模式,是[service-mesh模式],即任意一个微服务所在的机器上,都安装一个consul agent。缺点是,agent部署工作量大
**Client Addr**:这是用于Agent的客户端接口地址。这包括HTTP和DNS接口
的端口。默认情况下,这只绑定到本地主机。如果您更改此地址或端口,则运
行相关命令(如[consul members](https://www.consul.io/docs/commands
/members.html))时都必须指定`-http-addr`。 其他应用程序也可以使用HTTP
地址和端口来控制Consul。
---Client Addr默认127.0.0.1 :默认使用service-mesh模式(Agent的这个参数用于限制访问该节点的IP,使用默认时,表示只能本节点的服务调用Http API注册服务到Agent;使用0.0.0.0时则是任意ip都可以调用本节点Agent的Http API)
2.Consul外部服务:/v1/catalog/registry (一般不使用这种方式) 注册服务为外部服务(可以注册没有安装Agent的Node)
使用[consul ESM 与consul配合],为外部服务做健康检查
ESM外部服务管理。如果把服务注册时设置为外部服务,那么,agent就不会对这个服务进行健康检查,而是由consul-esm来进行检查。
3.Consul内部服务: /v1/node/services/registry (不是每个节点Node上都有代理Agent,节点上的服务注册到其他节点上的Agent)
注册到Agent上存在一个问题:单点故障,Agent死掉,则服务就算完好,也无法被发现(服务端负载均衡,给一个Nginx代理的方式,无法解决;使用客户端负载均衡,将服务分散,分别注册则有利于避免这个问题)
服务端负载均衡不可避免的要提供一个总的入口,将这个入口看做是服务,再将这个服务注册到注册中心,所存在的问题!!!!
正向代理 VS 反向代理
客户端负载均衡 VS 服务端负载均衡
对于Consul集群而言的Client模式的Agent,是Server的一种代理客户端
但是对于服务而言,client仍是服务端
服务内部需要使用consul api包的consulClient来连接consul的client或server,调用其中的http api完成注册等
两种服务注册客户端:
https://github.com/Ecwid/consul-api
https://github.com/rickfast/consul-client
服务中使用上述两种jar包的client去连接Consul Agent
服务在自注册时是会配置连接Consul的其中一个Agent的(可能是服务所在Node配置了Agent,也可能是另一个Node上配置了Agent)
4.虽然可以不使用Client模式,但是还是推荐使用,符合反熵,且每个Agent上能注册的服务是有限的,通过Client可以扩展 。
Node,Agent,Service
Node:实际的物理机器
Agent:机器上运行的一个Consul进程
Service:机器上运行的一个服务进程
检查分为:
1.Agent(Node)的健康检查
2.Service的健康检查
注册到Agent上的服务都会被注册到Agent上的check所检查;
check也可以精确到service上注册
3.外部服务:service和check不做关联,通过ESM关联对service做健康检查
服务调用者实现负载均衡--客户端负载均衡Ribbon
服务发现之后:基于服务名去发起请求调用
一个服务可能即是provider又是consumer:将自身注册consul集群同时从consul集群中获取服务
中心化(注册中心)---》去中心化(服务网格)
consul的服务网格是通过client+server实现
client作为代理,server作为代理层完成代理间的互相发现
9.服务的理解
整个Consul的体系中涉及到的元素,抽象出的Bean及对应的数据结构
二:关注于Provider
- 服务提供者自注册
spring-cloud-consul-discovery+spring boot actuator:
注册服务及配置健康检查相关配置(@EnableDiscoveryClient)
--指明:服务注册到哪?使用哪个endpoint做健康检查
提供者添加配置(application.yml)
server:
port: 9001 #提供者的端口
spring:
application:
name: spring-cloud-consul-producer
cloud:
consul:
host: localhost //consul Agent(client)
port: 8500
discovery:
tags: dev //注册到consul的服务的tags
serviceName: spring-cloud-consul-producer # 注册到consul的服务名称
healthCheckPath: /actuator/health
healthCheckInterval: 15s
healthCheckUrl: http://127.0.0.1:9001/actuator/health
register: true //是否注册本服务到注册中心
prefer-ip-address: false
2.consul支持配置文件注册的方式,使得服务本身无感知--官方推荐方式
三:关注于Consumer
服务发现有两层含义:
对于注册中心而言:每个Agent能查到其它Agent上的服务是一种服务发现
对于消费者而言:每个消费者根据服务名找到服务地址是另一种服务发现
服务消费者:配置好注册中心及消费者本身是否注册相关
Ribbon(或Feign):服务发现(消费),客户端负载均衡; (**以服务名请求服务)
1. 发现服务
@EnableDiscoveryClient --->DiscoveryClient 通过这个对象进行服务发现
List
2.指明某个或某些服务在客户端采用的负载均衡策略 (主启动类上标注)
@RibbonClients(value = {
@RibbonClient(name = "xxx",configuration = XxxRibbonConfig.class),
@RibbonClient(name = "demo",configuration = DemoRibbonConfig.class)
}) //配置服务名对应的负载均衡策略。
Ribbon支持自定义负载均衡策略
3. 使用 RestTemplate发起请求
@LoadBalanced //通过该注解实现客户端负载均衡
RestTemplate restTemplate; //发起服务调用请求
参考:https://yq.aliyun.com/articles/684607 cloud-consul
https://blog.csdn.net/sinat_30276961/article/details/84606263 ribbon
也可以直接使用Feign客户端发起http调用
Feign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign, 我们可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求,类似于Dubbo的RPC
使用方法:
@EnableFeignClients // 注解开启对 Feign Client 扫描加载处理
@FeignClient(name = "XXX") //服务名
Feign 如何结合 Ribbon 切换均衡算法??
# feign和ribbon结合,指定策略。feign默认的是轮询的策略,这里的配置可以自定义
MICROSERVICE-ORDER: //具体的服务名
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
指明的相关信息:
1.我要调用哪个服务
2.服务的哪个接口
3.这个服务采用的负载均衡策略
4.超时与重试
从服务到调用###(Consumer知道自己要消费的服务名)
注意:使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模板化的调用方法.但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用.所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义.在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它(以前是Dao接口上标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量