本篇博客参考学习视频

一、Eureka 服务注册与发现

① Eureka 基础知识

1. 服务治理

​ SpringCloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理。 在传统的 RPC 远程调用框架中, 管理每个服务与服务之间依赖关系比较复杂, 所以需要使用服务治理管理服务与服务之间依赖关系, 了以实现服务调用、 负载均衡、容错等, 实现服务发现与注册 。

2. 服务注册

image-20201008163431445

image-20201008163441176

3.Eureka 两组件

image-20201008163527932

② 单机 Eureka 构建步骤

1.IDEA 生成 EurekaServer 端服务注册中心 类似物业公司

建 Module

image-20201008163938347

改 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
34
35
36
37
<dependencies>
<!--eureka-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>${project.version}</version>
</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>

1.X 和 2.X 的对比说明

image-20201008164348553

写 YML

1
2
3
4
5
6
7
8
9
10
11
server:
port: 7001

eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

主启动

1
2
3
4
5
6
7
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class, args);
}
}

注意:需要在启动类上配置注解 @EnableEurekaServer,开启注册中心

测试

http://localhost:7001/ ,效果页面

image-20201008165537963

2.EurekaClient 端 cloud-provider-payment8001 将注册进 EurekaServer 成为服务提供者 provider

改 POM ( cloud-provider-payment8001)

1
2
3
4
5
<!--https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

1.X 和 2.X 的对比说明

image-20201008170119489

写 YML

1
2
3
4
5
6
7
8
eureka:
client:
# 表示是否将自己注册进eurekaServer 默认为 true。
register-with-eureka: true
# 是否从EureaServer 抓取已有的注册信息,默认为true.单节点无所谓,集群必须设置true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka

主启动

1
2
3
4
5
6
7
@EnableEurekaClient
@SpringBootApplication
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class, args);
}
}

添加:注解 @EnableEurekaClient

测试

image-20201008203122376

  • 微服务配置说明

image-20201008173128335

  • 自我保护机制

image-20201008173216519

3.EurekaClient 端 cloud-consumer-order80 将注册进 EurekaServer 成为服务消费者 consumer

改 POM

1
2
3
4
5
<!--https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

写 YML

1
2
3
4
5
6
7
8
9
spring:
application:
name: cloud-order-service
eureka:
client:
register-with-eureka: true
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka

主启动 @EnableEurekaClient

1
2
3
4
5
6
7
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}

测试

  • 先启动 EurekaServer, 7001 服务,在启动服务提供者 provider 8001 服务,在启动消费者 consumer 80

image-20201008204121007

image-20201008204201760

BUG

image-20201008210724219

image-20201008210736191

③ Eureka 构建步骤

1.Eureka 集群原理说明

image-20201008210953089

**微服务 RPC 远程服务调用最核心的是什么 **

1
高可用

解决办法:搭建 Eureka 注册中心集群,实现负载均衡+故障容错

2.EurekaServer 集群环境构建步骤

新建 cloud-eureka-server7002 和 POM

​ 参考 cloud-eureka-server7001 项目工程

修改映射配置

找到 C:\Windows\System32\drivers\etc 路径下的 hosts 文件 image-20201008213018672

修改映射配置添加进 hosts 文件

  • 127.0.0.1 eureka7001.com
  • 127.0.0.1 eureka7002.com

image-20201008221924946

写 YML

  • 以前单机

image-20201008213246584

  • 7001
1
2
3
4
5
6
7
8
9
10
11
server:
port: 7001

eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7002.com:7002/eureka/ #设置与 eureka server 交互的地址查询服务和注册服务都需要依赖这个地址
  • 7002
1
2
3
4
5
6
7
8
9
10
11
server:
port: 7002

eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/ #设置与 eureka server 交互的地址查询服务和注册服务都需要依赖这个地址

主启动类 (参考 cloud-eureka-server7001 的主启动类 )

1
2
3
4
5
6
7
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7002 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7002.class, args);
}
}

3.将支付服务 8001 微服务发布到上面 2 台 Eureka 集群配置中

YML

1
2
3
4
5
6
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版

image-20201008214921087

4.将订单服务 80 微服务发布到上面 2 台 Eureka 集群配置中

YML

1
2
3
4
5
6
7
eureka:
client:
register-with-eureka: true
fetchRegistry: true
service-url:
# defaultZone: http://localhost:7001/eureka
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版

image-20201008215358970

5.测试 01

  • 先要启动 EurekaServer, 7001/7002 服务,再要启动服务提供者 provider, 8001 服务,再要启动消费者, 80

image-20201008222218619

image-20201008222250676

6.支付服务提供者 8001 集群环境构建

新建 cloud-provider-payment8002 和 POM

​ 参考 cloud-provider-payment8001

写 YML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server:
port: 8002
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: 6090
mybatis:
mapperLocations: classpath:mapper/*.xml
type-aliases-package: com.oy.springcloud.entities # 所有Entity别名类所在包

eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
# 集群版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

主启动

1
2
3
4
5
6
7
@EnableEurekaClient
@SpringBootApplication
public class PaymentMain8002 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8002.class, args);
}
}

业务类 直接从 8001 粘贴

image-20201008223430791

修改 8001/8002 的 controller

1
2
@Value("${server.port}")
private String serverPort;
  • 8001 和 8002
image-20201008223844291

7.负载均衡

Bug: 订单服务访问地址不能写死

原本:(cloud-consumer-order80

image-20201008224333187

更改:

1
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

使用@LoadBalanced 注解赋予 RestTemplate 负载均衡的能力 (cloud-consumer-order80

image-20201008224958711

8.测试 02

  • 先要启动 EurekaServer, 7001/7002 服务
  • 再要启动服务提供者 provider, 8001/8002 服务
  • 在启动 consumer 80 服务
  • http://localhost/consumer/payment/get/1 **负载均衡生效, 8001/8002 端口交替出现 **

image-20201008225822628

④ actuator 微服务信息完善

1.主机名称:服务名称修改

修改 YML (cloud-provider-payment8001) 部分

1
2
instance:
instance-id: payment8001

image-20201009230434805

2.访问信息有 ip 信息提示

​ 当前问题:没有 ip 提示

修改 cloud-provider-payment8001 YML 部分

1
prefer-ip-address: true

image-20201016111308870

_效果_:

image-20201009230917967

⑤ 服务发现 Discovery

1.对于注册进 eureka 里面的微服务,可以通过服务发现来获取服务的信息

2.修改 cloud-provider-payment8001 的 Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Resource
private DiscoveryClient discoveryClient;

@GetMapping(value = "/payment/discovery")
public Object discovery(){
List<String> services = discoveryClient.getServices();
for (String element : services) {
log.info("**** element:"+ element);
}

List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");

for (ServiceInstance instance : instances) {
log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
}

return this.discoveryClient;
}

3.8001 主启动类

@EnableDiscoveryClient

1
2
3
4
5
6
7
8
@EnableEurekaClient
@EnableDiscoveryClient // 服务发现
@SpringBootApplication
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class, args);
}
}

4.测试

image-20201010153131926

⑥ Eureka 自我保护

1.故障现象

image-20201010153351564

2.导致原因

image-20201010153435587

image-20201010153445964

image-20201010153524632

image-20201010153542491

总结某时刻某一个微服务不可用了,Eureka 不会立即清理,依旧会对该服务的信息进行保存,属于 CAP 里的 AP 分支

3.怎么禁止自我保护(一般生产环境中不会禁止自我保护)

注册中心 eureakeServer 端 7001: 出 厂 默 认 , 自 我 保 护 机 制 是 开 启的:eureka.server.enable-self-preservation = true

  • 使用 eureka.server.enable-self-preservation = false 可以禁用自我保护模式

  • 在 eurekaServer 端 7001 处设置关闭自我保护机制

image-20201010154122092

效果图:

image-20201010154441508

生产者客户端 eureakeClient 端 8001

默认:

1
2
eureka.instance.lease-renewal-interval-in-seconds=30 单位为秒( 默认是 30 秒)
eureka.instance.lease-expiration-duration-in-seconds=90 单 位 为 秒( 默认是 90 秒)

配置:

image-20201010154942881
1
2
3
4
5
6
7
instance:
instance-id: payment8001
prefer-ip-address: true
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-renewal-interval-in-seconds: 1
#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
lease-expiration-duration-in-seconds: 2

4.测试

  • 7001 和 8001 都配置完成
  • 先启动 7001 再启动 8001 ,先关闭 8001 ,马上被删除了

image-20201010163755231

二、Zookeeper 服务注册与发现

① Eukeka 停止更新了怎么办

https://github.com/Netflix/eureka/wiki

② SpringCloud 整合 Zookeeper 代替 Eureka

1.注册中心 zookeeper

  • zookeeper 是一个分布式协调工具,可以实现注册中心功能

使用 docker 快速创建 zookeeper 容器

  • 关闭 Linux 服务器防火墙后启动 zookeeper 服务器

CentOS 7 关闭防火墙指令

1
2
3
4
5
6
7
8
9
10
11
// 查看当前防火墙状态如果防火墙处于开启状态,firewalld.service前面的点是高亮的,Active:active(开启))
systemctl status firewalld.service

//关闭当前的防火墙(仅对本次开机有效,重启后防火墙会再次启用)
systemctl stop firewalld.service

//永久关闭防火墙(重启后防火墙依然关闭)
systemctl disable firewalld.service

// 启动防火墙
systemctl start firewalld
  • zookeeper 服务器取代 Eureka 服务器,zk 作为服务器注册中心

2.服务提供者

新建 cloud-provider-payment8004

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?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>
<artifactId>clould</artifactId>
<groupId>com.oy</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>cloud-provider-payment8004</artifactId>
<description>Zookeeper服务提供者</description>

<dependencies>
<dependency>
<groupId>com.oy</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringBoot整合Zookeeper客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</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>

</project>

YML

1
2
3
4
5
6
7
8
9
10
11
server:
# 8004表示注册到zookeeper服务器的支付服务提供者端口号
port: 8004

spring:
application:
# 服务别名---注册zookeeper到注册中心的名称
name: cloud-provider-payment
cloud:
zookeeper:
connect-string: 116.63.177.72:2181

主启动类

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;


@EnableDiscoveryClient
@SpringBootApplication
public class PaymentMain8004 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8004.class, args);
}
}

Controller

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

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

@GetMapping(value = "/payment/zk")
public String paymentzk(){
return "springcloud with zookeeper:"+serverPort+"\t"+ UUID.randomUUID().toString();
}
}

启动 8004 注册进 zookeeper

image-20201010185203951

注意:启动后问题存在下面问题

image-20201010185426339

Why:

  • 解决 zookeeper 版本 jar 包冲突问题:

image-20201010185547065

  • 排出 zk 冲突后的新 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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?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>
<artifactId>cloud2020</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>cloud-provider-payment8004</artifactId>
<description>Zookeeper服务提供者</description>

<dependencies>
<!--SpringBoot整合Zookeeper客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<exclusions>
<!--先排除自带的zookeeper3.5.3-->
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加zookeeper3.4.9版本-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</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>

</project>

测试

image-20201010190241945

image-20201010190802924

思考: 服务节点是临时节点还是持久节点——是临时节点

3.服务消费者

新建 cloud-consumerzk-order80

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?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>
<artifactId>cloud2020</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>cloud-consumerzk-order80</artifactId>

<dependencies>
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringBoot整合Zookeeper客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<exclusions>
<!--先排除自带的zookeeper3.5.3-->
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加zookeeper3.4.9版本-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</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>

</project>

YML

1
2
3
4
5
6
7
8
9
10
server:
port: 80
spring:
application:
# 服务别名
name: cloud-consumer-order
cloud:
zookeeper:
# 注册到zookeeper地址
connect-string: localhost:2181

主启动

1
2
3
4
5
6
7
@SpringBootApplication
@EnableDiscoveryClient
public class OrderZkMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderZkMain80.class, args);
}
}

主业务类

  • bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.springcloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
* @Author OY
* @Date 2020/10/10
*/
@Configuration
public class ApplicationContextConfig {

@Bean
public RestTemplate restTemplate(){
return restTemplate();
}
}
  • controller
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
package com.springcloud.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
* @Author OY
* @Date 2020/10/10
*/

@RestController
@Slf4j
public class OrderZkController {

@Resource
private RestTemplate restTemplate;

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

@GetMapping("/consumer/payment/zk")
public String paymentInfo() {
return restTemplate.getForObject(INVOKE_URL + "/payment/zk", String.class);

}
}

验证测试

image-20201010193246059

访问测试地址

http://localhost/consumer/payment/zk

image-20201010193352456

三、Consul 服务注册与发现

① Consul 简介

1.是什么:https://www.consul.io/intro/index.html

image-20201011204018659

image-20201011204039409

2.能干嘛:

image-20201011204121943

  • 服务发现: 提供 HTTP 和 DNS 两种发现方式
  • 健康检查: 支持多种协议,HTTP、TCP、Docker、Shell 脚本定制化
  • KV 存储: Key,Value 的存储方式
  • 多数据中心: Consul 支持多数据中心
  • 可视化 Web 界面

3.下载

https://www.consul.io/downloads.html

4.怎么玩

https://www.springcloud.cc/spring-cloud-consul.html

② 安装并运行 Consul

1.官网安装说明

https://learn.hashicorp.com/consul/getting-started/install.html

2.下载完成后只有一个 consul.exe 文件,硬盘路径下双击运行,查看版本信息

image-20201011205359901

3.使用开发者模式启动

1
consul agent -dev

image-20201011205619155

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

image-20201011205709239

③ 服务提供者

新 建 Module 支 付 服 务 provider8006

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?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>
<artifactId>clould</artifactId>
<groupId>com.oy</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>cloud-providerconsul-payment8006</artifactId>

<dependencies>
<!--https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-consul-discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.oy</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

YML

1
2
3
4
5
6
7
8
9
10
11
server:
port: 8006
spring:
application:
name: consul-provider-payment
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}

主启动类

1
2
3
4
5
6
7
@EnableDiscoveryClient
@SpringBootApplication
public class PaymentMain8006 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8006.class, args);
}
}

主业务类 Controller

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

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

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

验证测试

http://localhost:8006/payment/consul

image-20201011211341291

④ 服务消费者

新 建 Module 消 费 服 务 order8006

​ cloud-consumerconsul-order80

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?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>
<artifactId>clould</artifactId>
<groupId>com.oy</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>cloud-consumerconsul-order80</artifactId>

<dependencies>
<!--https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-consul-discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.oy</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope></dependency>
</dependencies>
</project>

YML

1
2
3
4
5
6
7
8
9
10
11
12
server:
port: 80

spring:
application:
name: consul-consumer-order
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}

主启动类

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.oy.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class OrderConsulMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderConsulMain80.class, args);
}
}

配置 Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.oy.springcloud.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationConfig {

@LoadBalanced // 负载均衡
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}

Controller

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
package com.oy.springcloud.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
* @Author OY
* @Date 2020/10/11
*/
@RestController
@Slf4j
public class OrderConsulController {

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

@Resource
public RestTemplate restTemplate;

@GetMapping("/consumer/payment/consul")
public String payment(){
String result = restTemplate.getForObject(INVOME_URL+"/payment/consul",String.class );
return result;
}
}

验证测试

image-20201011214858615

访问测试地址:http://localhost/consumer/payment/consul

image-20201011215016107

⑤ 三个注册中心异同点

1.CAP

  • C: Consistency (强一致性)
  • A: Availability (可用性)
  • P: Partition tolerance (分区容错)

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

2.经典 CAP 图

image-20201011215345966

image-20201011215809145

AP(Eureka) 架构

当网络分区出现后,为了保证可用性,系统 B可以返回值,保证系统的可用性。

结论:违背了一致性 C 的要求,只满足可用性和分区容错,即 AP

image-20201011220139399

CP(Zookeeper/Consul) 架构

image-20201011220325077