文章目录
1. 简介
Consul 是 HashiCorp 公司推出来的开源产品。主要提供了:服务发现、服务隔离、服务配置等功能。相比于 其他注册中心组件Eureka 和Zookeeper,Consul 配置更加一站式,因为它内置了很多微服务常见的功能:服务发现与注册、分布式一致性协议实现、健康检查、键值对存储、多数据中心等,我们不再需要借助第三方组件来实现这些功能。
Spring Cloud Consul 具有如下特性:
- 支持服务治理:Consul作为注册中心时,微服务中的应用可以向Consul注册自己,并且可以从Consul获取其他应用信息
- 支持客户端负载均衡:提供Ribbon和Spring Cloud LoadBalancer实现负载均衡
- 支持Zuul:当Zuul作为网关时,可以从Consul中注册和发现应用
- 支持分布式配置管理:Consul作为配置中心时,使用键值对来存储配置信息
- 支持控制总线:可以在整个微服务系统中通过 Control Bus 分发事件消息
Spring Cloud Consul 中文文档:https://www.springcloud.cc/spring-cloud-consul.html
2. 安装
不同于 Eureka ,Consul 使用 Go 语言开发,所以我们需要先安装Consul 。
2.1 Windows环境安装
从官网直接下载软件,官网下载地址:https://www.consul.io/downloads.html。下载完成后只有一个exe文件,首先双击运行该文件;
在命令行中输入以下命令可以查看版本号:
consul --version
然后使用开发模式启动:
consul agent -dev
浏览器访问 http://localhost:8500 ,进入Consul首页。
2.2 Linux环境安装
在 Linux 中,首先执行如下命令下载 Consul:
wget https://releases.hashicorp.com/consul/1.6.2/consul_1.6.2_linux_amd64.zip
下载完成后解压压缩包
unzip consul_1.6.2_linux_amd64.zip
解压完成后,我们可以看到consul文件,然后执行以下命令启动consul:
./consul agent -dev -ui -node=consul-dev -client=192.168.91.128
参数说明:
- -dev: 表示开发模式启动;
- -ui:表示显示管理界面的web-ui;
- -node:表示节点在 web-ui界面上显示的名称;
- -client:指定客户端访问的ip,0.0.0.0表示所有客户端都可访问;
其他参数:
- -bootstrap-expect:表示server集群中最少的节点个数,低于这个值集群就不会工作(原理类似于Zookeeper,通常集群中的节点个数为奇数,方便进行选举,consul采用的是 raft算法);
- -data-dir:表示指定数据的存放目录(目录必须存在);
- -bind:表示绑定到哪个IP地址(有些服务器可能有多块网卡,需要进行配置);
注意:192.168.91.128应该为内网ip。还要确保8500端口可用
启动成功后,浏览器请求http://101.43.30.7:8500/ui/dc1/services,访问consul管理后台
集群部署Consul的相关命令:
./consul members:查看集群信息
./consul join consul服务IP:添加节点
./consul info:查看节点的具体信息
3. 使用
3.1 服务提供者
创建Spring Boot项目,作为服务提供者,添加以下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
成功创建项目后,application.properties添加如下配置:
spring.application.name=consul-provider
server.port=2000
#consul的主机地址
spring.cloud.consul.host=101.43.30.7
#conusl的端口
spring.cloud.consul.port=8500
#服务的名称
spring.cloud.consul.discovery.service-name=consul-provider
spring.cloud.consul.discovery.heartbeat.enabled=true
在启动类上开启服务发现的功能:
@SpringBootApplication
//开启服务发现功能
@EnableDiscoveryClient
public class ConsulProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulProviderApplication.class, args);
}
}
启动项目,访问consul管理后台界面,可以看到已经注册成功。
(如果服务总是报红叉,则需要在application.yml配置文件中增加spring.cloud.consul.discovery.heartbeat.enabled=true,打开Consul的心跳机制)
创建HelloController添加接口/hello
@RestController
public class HelloController {
@Value("${server.port}")
Integer port;
@GetMapping("/hello")
public String hello(){
return "hello" + port;
}
}
对项目进行打包,命令行启动多一个provider实例:
java -jar consul-provider-0.0.1-SNAPSHOT.jar --server.port=6000
consul管理后台可以看到有两个provider实例
3.2 服务消费者
创建Spring Boot项目consul-consumer,作为服务消费者,添加以下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
成功创建项目后,application.properties添加如下配置:
spring.application.name=consul-consumer
server.port=2002
#consul的主机地址
spring.cloud.consul.host=101.43.30.7
#conusl的端口
spring.cloud.consul.port=8500
#服务的名称
spring.cloud.consul.discovery.service-name=consul-consumer
在启动类上开启服务发现的功能,并注入RestTemplate:
@SpringBootApplication
@EnableDiscoveryClient
public class ConsulConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulConsumerApplication.class, args);
}
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
测试服务调用
@RestController
public class HelloController {
@Autowired
LoadBalancerClient loadBalancerClient;
@Autowired
RestTemplate restTemplate;
@GetMapping("/hello")
public void hello() {
ServiceInstance choose = loadBalancerClient.choose("consul-provider");
System.out.println("服务地址:" + choose.getUri());
System.out.println("服务名称:" + choose.getServiceId());
String s = restTemplate.getForObject(choose.getUri() + "/hello",
String.class);
System.out.println(s);
}
}
这里通过loadBalancerClient获取要调用的ServiceInstance,获取到调用地址之后再使用RestTemplate去调用。浏览器请求http://localhost:2002/hello ,查看控制台的请求结果。
3.3 配置中心
我们还可以在consul中实现服务的统一配置,创建Maven模块consul-config,在pom.xml中添加如下依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>top.javahai</groupId>
<artifactId>consul-config</artifactId>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
添加配置文件application.yml,配置启用dev环境:
spring:
profiles:
active: dev
添加配置文件bootstrap.yml,对Consul的配置功能进行配置:
server:
port: 9101
spring:
application:
name: consul-config
cloud:
consul:
host: localhost
port: 8500
discovery:
serviceName: consul-config
#打开心跳机制
heartbeat:
enabled: true
config:
#是否启用配置中心功能
enabled: true
#设置配置值的格式
format: yaml
#设置配置所在目录
prefix: config
#设置配置的分隔符
profile-separator: ':'
#配置key的名字,由于Consul是K/V存储,配置存储在对应K的V中
data-key: data
创建ConfigController,提供接口/configInfo,从Consul配置中心中获取配置信息.使用@RefreshScope注解实现动态加载配置文件。
@RestController
@RefreshScope
public class ConfigController {
@Value("${config.info:}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo() {
return configInfo;
}
}
在Consul后台添加如下配置:
添加配置存储的key为:
config/consul-config:dev/data
添加配置存储的value为:
config:
info:"config info onsul-config for dev"
启动项目调用/configinfo接口查看配置信息。
我们修改Consul中的配置信息,再次调用查看配置的接口,就会发现配置也刷新了。这是因为Consul使用其自带的Control Bus 实现了一种事件传递机制,从而实现了动态配置刷新功能。
4. Consul的CAP理论运用
4.1 CAP理论
CAP理论是分布式架构中重要理论。C(Consistency)一致性、A(Availablity)可用性、P(Partition Tolerance)分区容错性。分布式系统不可能同时满足三个特性,最多只能满足其中两个特性。根据实际情况选择不同的特性组合对应的技术栈。
-
一致性:对于客户端的每次读操作,要么读到的是最新的数据,要么读取失败。换句话说,一致性是站在分布式系统的角度,对访问本系统的客户端的一种承诺:要么我给您返回一个错误,要么我给你返回绝对一致的最新数据,不难看出,其强调的是数据正确。
-
可用性:任何客户端的请求都能得到响应数据,不会出现响应错误。换句话说,可用性是站在分布式系统的角度,对访问本系统的客户的另一种承诺:我一定会给您返回数据,不会给你返回错误,但不保证数据最新,强调的是响应不出现错误。
-
分区容忍性:由于分布式系统通过网络进行通信,网络是不可靠的。当任意数量的消息丢失或延迟到达时,系统仍会继续提供服务,不会挂掉。换句话说,分区容忍性是站在分布式系统的角度,对访问本系统的客户端的再一种承诺:我会一直运行,不管我的内部出现何种数据同步问题,强调的是不挂掉。
而CAP 在分布式系统不可能同时满足,只能取其中2个原因是 如果C是第一需求的话,那么会影响A的性能,因为要数据同步,不然请求结果会有差异,但是数据同步会消耗时间,期间可用性就会降低。如果A是第一需求,那么只要有一个服务在,就能正常接受请求,但是返回结果的正确性便不能保证,原因是在分布式部署的时候,节点间的数据同步的过程需要一定的时间。再如果,同时满足一致性和可用性,那么分区容错性就很难保证了。对于数据没有同步的节点,只能暂停接收请求,这就违背了分区容错性。
4.2 Consul的运用
Consul 遵循CAP原理中的CP原则,保证了强一致性和分区容错性,且使用的是Raft算法,比Zookeeper使用的Paxos算法更加简单。虽然保证了强一致性,但是可用性就相应下降了,例如服务注册的时间会稍长一些,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用。Consul 保证了强一致性但牺牲了可用性。
4.3 注册中心的对比
Eureka:主要支持的是AP,强调高可用和分区容错;
Consul和Zookeeper:主要支持CP,强调数据一致性和分区容错。
Eureka拥有一个自我保护机制,当在90s内如果有过多的心跳包丢失,Eureka不会直接注销该服务,而是选择采用保护机制不去注销服务,等到90s到期如果仍然不能接受心跳包就直接注销,这种为了保证最大吞吐量而牺牲数据一致性的思想就是AP;
Zookeeper采用创建临时节点的机制来注册服务,由于是临时节点在连接断开时就会立刻被删除,对应着服务就被注销,这种思想对应的就是CP;
Consul在微服务器断开时会立刻停止服务,必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用的方式,来保证数据一致性原则。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/44270.html