失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 《深入理解 Spring Cloud 与微服务构建》第十二章 服务注册和发现 Consul

《深入理解 Spring Cloud 与微服务构建》第十二章 服务注册和发现 Consul

时间:2023-12-16 21:50:07

相关推荐

《深入理解 Spring Cloud 与微服务构建》第十二章 服务注册和发现 Consul

《深入理解 Spring Cloud 与微服务构建》第十二章 服务注册和发现 Consul

文章目录

《深入理解 Spring Cloud 与微服务构建》第十二章 服务注册和发现 Consul一、什么是 Consul1.基本术语2.Consul 的特点和功能3.Consul 的原理4.Consul 的基本架构5.Consul 服务注册发现流程二、Consul 与 Eureka 比较三、下载和安装 Consul四、使用 Spring Cloud Consul 进行服务注册和发现1.服务提供者 consul-provider2.服务消费者五、使用 Spring Cloud Consul Config 做服务配置中心六、动态刷新配置

一、什么是 Consul

Consul 是 HashiCorp 公司推出的开源软件,使用 Go 语言编写,提供了分布式系统的服务注册和发现、配置等功能,这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格。Consul 不仅具有服务治理的功能,而且使用分布式一致性协议 PAFT 算法实现,有多数据中心的高可用方案,并且很容易和 Spring Cloud 等微服务框架集成,具有简单、以用、可插排等特点。简而言之,Consul 提供了一种完整的服务网格解决方案

1.基本术语

代理(Agent):是一直运行在 Consul 集群中的每个节点上的守护进程,通过运行 consul agent 命令来启动。代理可以以客户端或服务端模式运行。无论是客户端节点,还是服务端节点,都必须运行代理,因此将节点称为客户端或服务器更容易理解。所有代理都可以通过 DNS 或 HTTP 接口来检查服务,并保持服务同步客户端(Client):客户端是所有 RPC 转发到服务端的代理。这个客户端是相对无状态的。客户端唯一执行的后台活动是加入 LAN gossip 池,资源开销很小服务端(Server):服务端是具有扩展责任的代理,包括参与 Raft 选举、维护集群状态、响应 RPC 查询、与其他数据中心交换 WAN,以及将查询转发给领导者(Leader)或远程数据中心数据中心(Data Center):是一个私有的、低延迟且高带宽的网络环境,由多个客户端和服务端构成共识(Consensus):在文档中,我们使用共识来表示对当选领导者的协议以及交易顺序的协议。由于这些事务应用于有限状态机,因此我们对共识的定义意味着复制状态机的一致性Goosip:Consul 建立在 Serf 的基础上,它提供了一个完整的 Gossip 协议LAN Gossip:是指局域网 Gossip,包含位于同一个数据中心的所有节点WAN Gossip:是指仅包含服务端的 WAN Gossip 池。这些服务端位于不同的数据中心,通常通过互联网或广域网进行通信远程调用(RPC):是一个允许客户端请求服务端的呢请求-响应机制

2.Consul 的特点和功能

服务发现:Consul 客户端可以向 Consul 注册服务,例如 API 服务或者 MySQL 服务,其他客户端可以使用 Consul 来发现服务的提供者。Consul 支持使用 DNS 或 HTTP 来注册和发现服务运行时健康检查:Consul 客户端可以提供任意数量的运行状态检查机制,这些检查机制可以与给定服务(WEB 服务器返回 200 OK)或本地节点(内存利用率低于 90%)相关联。这些信息可以用来监控群集的运行状况,服务发现组件可以使用监控信息来路由流量,使流量远离不健康的服务KV 存储:应用程序可以将 Consul 的键/值存储起来用于任何需求,包括动态配置、功能标记、协调、领导者选举等。KV 存储采用 HTTP API,因此易于使用安全服务通信:Consul 可以为服务生成和分发 TLS 证书,以建立相互的 TLS 连接多数据中心:Consul 支持多个数据中心,这意味着 Consul 用户不必担心构建额外的抽象层来扩展到多个区域

3.Consul 的原理

每个提供服务的节点都运行了 Consul 的代理(Agent),运行代理时不需要服务发现和获取配置的 KV 键值对,代理只负责监控检查。代理节点可以和一个或多个 Consul 服务端通信。Consul 服务端使存储和复制数据的节点,采用 RAFT 算法保证了数据一致性,并选出了领导者,建议使用 3 台或 5 台 Consul 服务端,以避免发生数据丢失的情况。Consul 支持多个数据中心,建议每个数据中心使用多个 Consul Server 作为一个集群

如果微服务组件需要发现服务,可以查询任何 Consul 服务端或任何 Consul 代理。如果是查询 Consul Agent,Consul Agent 会自动将查询请求转发给 Consul 服务端。发生跨数据中心服务发现或配置请求时,本地 Consul 服务端会将请求转发到远程数据中心,并返回结果

4.Consul 的基本架构

Consul 的基本架构如图所示:

其中有两个数据中心,标记为 “DATACENTER 1” 和 “DATACENTER 2”。在大型分布式系统中,多数据中心是十分常见的,Consul 对多数据中心有着非常强大的支持

在每个数据中心中,客户端和服务端是混合的。一般建议使用奇数个服务端,比如 3 台或 5 台。这是基于有故障情况下的可用性和性能之间的权衡结果,因为越多的机器加入,则达成共识的速度越慢。但这并不是限制客户端的数量,客户端可以很容易地扩展到数千台或数万台

同一个数据中心的所有节点都加入了 Gossip 协议,意味着 Gossip 协议池包含该数据中心的所有节点,这样做有如下 3 个目的:

不需要在客户端上配置服务端地址,服务发现都是自动完成的检测节点故障的工作不放在服务端上,而是分布式的,使得故障检测比心跳机制有更高的可扩展性数据中心可被用作消息传递层,比如发生领导者选举等重要事件时起到通知作用

数据中心中的每个服务端节点都是 Raft 节点集合的一部分。他们共同选举一个领导者,即一个具有额外职责的选定服务端。领导者负责处理所有查询和事务,作为共识协议的一部分,还必须将事务复制到所有对等体。因此当非领导者的服务端收到 RPC 请求时,它会将请求转发给群集的领导者

服务端节点也作为 WAN Gossip 协议池的一部分,不同于 LAN Gossip 协议池的是,它对较高的网络延迟进行了优化,并且只包含其它 Consul 服务端节点。这个协议池的作用是允许数据中心能够以低接触的方式发现彼此,使得一个新数据中心可以很容易地加入现存的 WAN Gossip 协议池。因为服务端都运行在这个协议池中,支持跨数据中心请求。当一个服务端收到来自另一个数据中心的请求时,它会将其转发到正确数据中心的随机服务端。该服务端再转发给本地领导者

数据中心之间的耦合度非常低,但由于故障检测、连接缓存和多路复用等机制,跨数据中心请求相对快速且可靠

5.Consul 服务注册发现流程

Consul 最广泛的用途之一就是作为服务注册中心,同时也可以作为配置中心。作为服务注册中心时,Consul 同 Eureka 类似,其注册和发现过程中有 3 个角色,分别是服务注册中心、服务提供者、服务消费者

服务提供者(Provider)启动时,会向 Consul 发送一个请求,将其 Host、IP、应用名、健康检查等元数据信息发送给 ConsulConsul 接收到服务提供者的注册后,定期向其发送健康检查的请求,检验服务提供者是否健康服务消费者(Consumer)会从注册中心 Consul 中获取服务注册列表,当服务消费者消费服务时,会根据服务命从服务注册列表中获取具体服务的实例(一个或者多个)信息,再根据负载均衡策略完成服务的调用

二、Consul 与 Eureka 比较

Eureka 是 Netflix 公司开源的服务注册中心组件,是 Spring Cloud 官方比较推荐的服务注册中心解决方案,在 Eureka 的架构体系中,分为 Eureka 服务端和 Eureka 客户端。Eureka 服务端可以支持多数据中心,每个数据中心有一组 Eureka 服务端。通常,Eureka 客户端使用嵌入式 SDK 来注册和发现服务

Eureka 使用注册列表复制的方式提供弱一致的服务视图。当 Eureka 客户端向 Eureka 服务端注册时,该 Eureka 服务端将尝试复制到其它 Eureka 服务端,但不提供强一致性保护。服务注册成功后,要求 Eureka 客户端对 Eureka 服务端进行心跳健康检测。不健康的服务或节点将停止心跳,从而导致他们的监控检查超时,并从注册表中删除。服务注册的请求可以路由到任何 Eureka 服务端,Eureka 服务端可以提供过时或丢失的数据。这种简化的模型能够轻松地搭建 Eureka 服务端集群的高可用和强扩展性

相比 Eureka,Consul 提供了更多高级功能,包括更丰富的运行时健康检查、键值存储和多数据中心的相互感知。Consul 提供了强一致性的保证,因为 Consul 服务端使用 Raft 协议及逆行状态的复制。Consul 支持丰富的运行时健康检查,包括 TCP、HTTP、Ngios、Sensu 兼容脚本等。Consul 客户端基于 Gossip 的健康检查。服务注册请求会被路由到 Consul 领导者的节点

Consul 的强一致性意味着它需要用领导者选举和集群协调来锁定服务。Eureka 采用的是 P2P 的复制模式,不保证复制操作一定成功;Eureka 不提供强一致性的保证,而是提供一个最终一致性的服务实例视图。Eureka 客户端在 Eureka 服务端的注册信息有一个带期限的服务续约,一旦 Eureka 服务端在指定时间内没有收到 Eureka 客户端的心跳,则 Eureka 服务端会认定 Eureka 客户端注册的服务是不健康的。Consul 的代理(Agent)相当于 Netflix Ribbon + Netflix Eureka 客户端,而且对应用来说相对透明,同时,相比 Eureka 这种集中式的心跳检测机制,Consul 的代理可以参与到基于 Goosip 协议的健康检查中,分散了服务端的心跳检测压力。除此之外,Consul 为多数据中心提供了开箱即用的原生支持

三、下载和安装 Consul

Consul 使用 Go 语言编写,支持 Linux、Mac、Windows 等操作系统。到 Consul 官网 中下载安装包,下载完成后解压到计算机目录下,解压成功后,只有一个可执行的 consul.exe 文件。打开 cmd 终端,切换到安装目录下,执行以下命令:

consul --version

终端显示如下信息:

这样证明 C瓯南苏拉下载成功,并且可以执行

Consul 的常见执行命令如下表所示:

更多的 Consul 执行命令:Consul 官方网站

现在以开发者模式启动 Consul,使用 cmd 命令终端启动,启动命令如下:

consul agent -dev

在终端界面上,可以看到启动的日志,Consul 默认的访问端口为 8500.启动成功后,在浏览器上访问 http://lcoalhost:8500,显示的主界面如图所示:

随着 Eureka 2.0 版本的闭源,作为服务注册中心,Consul 在以企业级 Spring Cloud 为服务系统中将有着更加广泛的应用。接下来以案例的形式来讲解如何使用 Consul 作为服务注册中心和分布式配置中心

四、使用 Spring Cloud Consul 进行服务注册和发现

本案例一共有两个应用,应用信息如下表所示:

1.服务提供者 consul-provider

创建一个主 Maven 工程,然后创建一个 Spring Boot 子工程 consul-provider,在工程的 pom 文件中引入以下依赖,包括 consul-discovery 的起步依赖,该依赖是 spring cloud consul 用来向 consul 注册和发现服务的依赖,采用 REST API 方式进行通信。另外加上 WEB 的起步依赖,用于对外提供 REST API。代码如下:

<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><parent><artifactId>Consul</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>consul-provider</artifactId><properties><piler.source>8</piler.source><piler.target>8</piler.target></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-discovery</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies></project>

在工程的配置文件 application.yml 中做如下配置,代码如下:

server:port: 8763spring:application:name: consul-providercloud:consul:host: localhostport: 8500discovery:serviceName: consul-providerheartbeat:enabled: true

在上述配置中,指定了程序的启动端口为 8763,应用名为 consul-provider,consul 注册中心的地址为 localhost:8500

在程序的启动类 ConsulProviderApplication 中加上 @EnableDiscoveryClient 注解,开启服务发现的功能,代码如下:

package com.sisyphus;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication@EnableDiscoveryClientpublic class ConsulProviderApplication {public static void main(String[] args) {SpringApplication.run(ConsulProviderApplication.class, args);}}

写 RESTAPI,该 API 为一个 GET 请求,返回当前程序的启动端口,代码如下:

package com.sisyphus.controller;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HiController {@Value("${server.port}")String port;@GetMapping("/hi")public String home(@RequestParam String name){return "hi " + name + ", i am from port:" + port;}}

启动工程,在浏览器上访问 http://localhost:8500,页面显示 consul-provider,表示已经成功注册到 Consul 注册中心:

2.服务消费者

服务消费者的搭建过程与服务提供者类似,在 pom 文件中引入依赖,在配置文件 application.yml 做与服务提供者相同的配置,不同之处在于端口为 8765,服务名为 consul-consumer

然后写一个 FeignClient,该 FeignClient 调用 consul-provider 的 REST API,代码如下:

package com.sisyphus.feign;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;@FeignClient(value = "consul-provider")public interface EurekaClientFeign {@GetMapping(value = "/hi")String sayHiFromClientEureka(@RequestParam(value = "name") String name);}

Service 层代码如下:

package com.sisyphus.service;import com.sisyphus.feign.EurekaClientFeign;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class HiService {@AutowiredEurekaClientFeign eurekaClientFeign;public String sayHi(String name){return eurekaClientFeign.sayHiFromClientEureka(name);}}

对外提供一个 REST API,该 API 调用了 consul-provider 的服务,代码如下:

package com.sisyphus.controller;import com.sisyphus.service.HiService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HiController {@AutowiredHiService hiService;@GetMapping("/hi")public String sayHi(@RequestParam(defaultValue = "sisyphus", required = false) String name){return hiService.sayHi(name);}}

在浏览器上访问 http://localhost:8765/hi,浏览器响应如下:

这说明 consul-consumer 已经成功调用了 consul-provider 服务

五、使用 Spring Cloud Consul Config 做服务配置中心

Consul 不仅能用来服务注册和发现,而且 Consul 支持键值对的存储,可以用来做分布式配置中心。Spring Cloud 提供了 Spring Cloud Consul Config 依赖去和 Consul 相集成,用来做分布式配置中心

本案例再上一个案例的 soncul-provider 基础上进行改造。首先在工程的 pom 文件上加上 consul-config 的起步依赖,代码如下:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-config</artifactId></dependency>

然后修改配置文件 application.yml ,代码如下:

server:port: 8763spring:profiles:active: dev

上述配置文件指定了 Spring Boot 工程在启动时读取的 profiles 为 dev。然后在工程的启动配置文件 bootstrap.yml 文件中加上以下配置,代码如下:

spring:application:name: consul-providercloud:consul:host: localhostport: 8500discovery:service-name: consul-providerheartbeat:enabled: trueconfig:enabled: trueformat: yamlprefix: configdefaultContext: applicationprofileSeparator: ':'data-key: data

spring.cloud.consul.config 的配置项描述信息如下:

Eabled:设置 config 是否启用,默认为 trueFormat:设置配置的值得格式,可以为 yaml 和 propertiesPrefix:设置配置的基本目录,比如 configdefaultContext:设置默认的配置,被所有的应用读取,本例中未用profileSeparator profiles:设置分隔符,默认为 “,”data-key:为应用配置得 key 名字,值为整个应用配置的字符串

在浏览器上访问 consul 的 Key/Value 存储的管理界面,即 http://localhost:8500/ui/dc;/kv,创建一条记录其中 Key 值为 cofig/consul-provider:dev/data,Value 值如下所示:

root:bar: bar1server:port: 8081

在 consul-provider 工程中创建一个 REST API,该 API 返回从 Consul 配置中心读取 foo.bar 的值,代码如下:

package com.sisyphus.controller;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class FooBarController {@Value("${foo.bar")String fooBar;@GetMapping("/foo")public String getFooBar(){return fooBar;}}

启动工程,可以看到程序的启动端口为 8081,也就是在 Consul 的配置中心配置的 server.port 端口。工程启动完成后,在浏览器上访问呢 http:locahost:8081/foo,页面 显示 bar1,由此可知,应用 consul-provider 已经成功从 Consul 的配置中心读取了 foo.bar 的配置

六、动态刷新配置

在使用 Spring Cloud Config 作为配置中心时,可以使用 Spring Cloud Config Bus 动态刷新配置。Spring Cloud Consul 默认支持动态刷新,在需要动态刷新的类加上 @RefreshScope 注解即可,修改代码如下:

package com.sisyphus.controller;import org.springframework.beans.factory.annotation.Value;import org.springframework.cloud.context.config.annotation.RefreshScope;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RefreshScopepublic class FooBarController {@Value("${foo.bar}")String fooBar;@GetMapping("/foo")public String getFooBar(){return fooBar;}}

启动 consul-provider 工程,在浏览器上访问 http://localhost:8081/foo,页面显示 bar1。然后在浏览器上访问 consul 的 KV 存储的管理界面,修改 config/consul-provider:dev/data 的值,修改后的值如下:

foo:bar: bar2server:port: 8081

此时在不重启 consul-provider 工程的情况下,在浏览器上访问 http://localhost:8081/foo,页面显示 bar2,可见 foo.bar 的最新配置在工程不重启的情况下已经生效

如果觉得《《深入理解 Spring Cloud 与微服务构建》第十二章 服务注册和发现 Consul》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。