Cloud技术栈

Consul简介

image-20200707085404344

Consul 是 HashiCorp 公司推出的开源产品,用于实现分布式系统的服务发现、服务隔离、服务配置,这些功能中的每一个都可以根据需要单独使用,也可以同时使用所有功能。Consul 官网目前主要推 Consul 在服务网格中的使用。

与其它分布式服务注册与发现的方案相比,Consul 的方案更“一站式”——内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具。Consul 本身使用 go 语言开发,具有跨平台、运行高效等特点,也非常方便和 Docker 配合使用。

Consul 的主要特点有:
Service Discovery : 服务注册与发现,Consul 的客户端可以做为一个服务注册到 Consul,也可以通过 Consul 来查找特定的服务提供者,并且根据提供的信息进行调用。

Health Checking: Consul 客户端会定期发送一些健康检查数据和服务端进行通讯,判断客户端的状态、内存使用情况是否正常,用来监控整个集群的状态,防止服务转发到故障的服务上面。

KV Store: Consul 还提供了一个容易使用的键值存储。这可以用来保持动态配置,协助服务协调、建立 Leader 选举,以及开发者想构造的其它一些事务。

Secure Service Communication: Consul 可以为服务生成分布式的 TLS 证书,以建立相互的 TLS 连接。 可以使用 intentions 定义允许哪些服务进行通信。 可以使用 intentions 轻松管理服务隔离,而不是使用复杂的网络拓扑和静态防火墙规则。

Multi Datacenter: Consul 支持开箱即用的多数据中心,这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域。

Consul 角色
Server: 服务端, 保存配置信息, 高可用集群, 在局域网内与本地客户端通讯, 通过广域网与其它数据中心通讯。 每个数据中心的 Server 数量推荐为 3 个或是 5 个。

Client: 客户端, 无状态, 将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群。

image-20200707085636772

安装和使用

https://www.consul.io/downloads,选择好系统版本

image-20200707085722378

下载完成之后解压

image-20200707085824246

压缩包中只有一个consul.exe文件,点击运行。点击后在此目录中输入cmd,进入命令行界面。

image-20200707085952916

输入consul -version查看版本信息,查看成功,说明consul启动成功!

image-20200707090058209

接着使用开发模式启动consulconsul agent -dev

image-20200707091025942

通过以下地址可以访问Consul的首页:http://localhost:8500

image-20200707091123818

成功启动!

服务提供者注册

新建Module支付服务cloud-providerconsul-payment8006

pom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<dependencies>
<!--SpringCloud consul-server-->
<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>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

yml

image-20200707091605355

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
##consul服务端口号
server:
port: 8006

spring:
application:
name: consul-provider-payment

##consul注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}

主启动类

使用@EnableDiscoveryClient注解,该注解1.可以获取服务信息,2.用于向consul或者zookeeper作为注册中心的时候提供注册服务。

image-20200707091803510

1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
//用于向consul或者zookeeper作为注册中心的时候提供注册服务。
@EnableDiscoveryClient
public class PaymentMain8006 {

public static void main(String[] args) {

SpringApplication.run(PaymentMain8006.class, args);
}
}

controller

访问返回输出语句带项目端口

image-20200707091857086

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@Slf4j
public class PaymentController {

@Value("${server.port}")
private String serverPort;

@RequestMapping("/payment/consul")
public String paymentConsul(){
return "springCloud with consul:"+serverPort+"\t"+ UUID.randomUUID().toString();
}
}

测试

启动8006项目

image-20200707092026174

查看consul服务页面,服务注册成功!

image-20200707092046934

点击查看服务详细信息

image-20200707092248253

访问http://localhost:8006/payment/consul

GIF921

服务访问成功!

服务消费者注册

新建Module消费服务cloud-consumerconsul-order80

image-20200707092844952

pom

与服务提供者一样,主要导入spring-cloud-starter-consul-discovery依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<dependencies>
<!--SpringCloud consul-server-->
<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>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

yml

与服务提供者8006几乎完全一致,只有端口号的改变,和名称。

image-20200707093735699

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
##consul服务端口号
server:
port: 80

spring:
application:
name: consul-consumer-payment

##consul注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}

主启动类

这里的@EnableDiscoveryClient作用是用于服务注册与发现功能,当前没有使用该功能。所以该注解可以注释

image-20200707093232520

1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
//用于向consul或者zookeeper作为注册中心的时候提供注册服务。
@EnableDiscoveryClient
public class OrderConsumerMain80 {

public static void main(String[] args) {

SpringApplication.run(OrderConsumerMain80.class, args);
}
}

RestTemplate

使用Rest Template调用服务提供者提供的服务,配置Rest Template

image-20200707093420449

1
2
3
4
5
6
7
8
9
@Configuration
public class ApplicationContextConfig {

@Bean
@LoadBalanced//使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}

controller

image-20200707093534960

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RestController
@Slf4j
public class OrderConsulController {


public static final String INVOKE_URL = "http://consul-provider-payment";

@Resource
private RestTemplate restTemplate;

@GetMapping("/consumer/payment/consul")
public String paymentInfo(){

String result = restTemplate.getForObject(INVOKE_URL+"/payment/consul",String.class);

return result;
}
}

测试

启动OrderConsumerMain80

image-20200707095500786

查看consul服务页面,服务注册成功!

image-20200707095528773

访问http://localhost/consumer/payment/consul

GIF954

服务访问成功!

三个服务注册中心异同

组件名 语言 CAP 服务健康检查 对外暴露接口 SpringCloud集成
Eureka Java AP 可配支持 HTTP 已集成
Consul Go CP 支持 HTTP/DNS 已集成
Zookeeper Java CP 支持 客户端 已集成

CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。

一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)

可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)

分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。

CAP原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。如果在某个分布式系统中数据无副本, 那么系统必然满足强一致性条件, 因为只有独一数据,不会出现数据不一致的情况,此时C和P两要素具备,但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问,此时可用性条件就不能被满足,即在此情况下获得了CP系统,但是CAP不可同时满足 [1] 。

CAP理论关注粒度是数据,而不是整体系统设计的策略

由于我们使用的是分布式微服务架构,P要永远保证!

image-20200707100656437

image-20200707100702823

image-20200707100746962

AP架构当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性。违背了一致性C的要求,只满足可用性和分区容错

image-20200707100753310

image-20200707100805766

CP架构当网络分区出现后,为了保证一致性,就必须拒绝请求,否则无法保证一致性。违背了可用性A的要求,只满足一致性和分区容错。

image-20200707100811451