Written in the front: This is a document on the topic of microservices, including the components commonly used in microservices. If you have any questions, you can find the answers you are looking for in the overall document.
Registration Center
Knowledge Index
- What is a registry
- cap theorem
- Registry comparison
- service registration
- service call
1 What is a registry
When microservices call each other, they need to know the specific address of the called service and whether it is healthy (whether the server responds), which requires the registry to have these two capabilities: 1. The ability to allow service registration, 2. The ability to monitor services . If there is only one registry, our system cannot run normally when it cannot provide services for various reasons. Therefore, the registry is required to have the ability to cluster, and the data between clusters must be consistent. During failover of the host, the data of the master and slave nodes may be inconsistent, which may result in the incorrect service list being obtained when the service is called. Therefore, it must also have high availability and consistent cluster capabilities.
2 Spring Cloud supported registries and comparisons
2.1 cap theorem
CAP原则
Also known as CAP定理
, refers to in a distributed system, consistency ( Consistency
), availability ( Availability
), partition fault tolerance ( Partition tolerance
). CAP 原则
It means that these three elements can only achieve two points at most at the same time, and it is impossible to take care of all three.
Consistency 一致性
: Whether all data backups have the same value at the same time. (equivalent to all nodes accessing the same latest copy of data)
Availability 可用性
: Whether the cluster as a whole can still respond to the client's read and write requests after some nodes in the cluster fail. (High availability for data updates)
Partition Tolerance 容错性
: In terms of practical effect, the partition is equivalent to the time limit for communication. If the system cannot achieve data consistency within the time limit, it means that a partition has occurred, and a choice must be made between C and A for the current operation.
CAP原则
的精髓就是要么AP
,要么CP
,要么AC
,但是不存在CAP
。如果在某个分布式系统中数据无副本, 那么系统必然满足强一致性条件, 因为只有独一数据,不会出现数据不一致的情况,此时C和P两要素具备,但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问,此时可用性条件就不能被满足,即在此情况下获得了CP
系统,但是CAP
不可同时满足。
2.2 注册中心对比
Nacos | Eureka | Consul | Zookeeper | |
---|---|---|---|---|
一致性协议 | CP+AP | AP | CP | CP |
健康检查 | TCP/HTTP/MYSQL/Client Beat | Client Beat | TCP/HTTP/gRPC/Cmd | Keep Alive |
负载均衡策略 | 权重/metadata/Selector | Ribbon | Fabio | — |
雪崩保护 | 有 | 有 | 无 | 无 |
自动注销实例 | 支持 | 支持 | 不支持 | 支持 |
访问协议 | HTTP/DNS | HTTP | HTTP/DNS | TCP |
监听支持 | 支持 | 支持 | 支持 | 支持 |
多数据中心 | 支持 | 支持 | 支持 | 不支持 |
跨注册中心同步 | 支持 | 不支持 | 支持 | 不支持 |
SpringCloud集成 | 支持 | 支持 | 支持 | 支持 |
Dubbo集成 | 支持 | 不支持 | 不支持 | 支持 |
K8S集成 | 支持 | 不支持 | 支持 | 不支持 |
其中Eureka
2.x版本已经宣布闭源,Nacos
在后续Spring CloudAlibaba
章节中会介绍,本篇我们主要通过Consul
来演示注册中心的配置及使用。
3 Consul
3.1 Consul介绍
Consul
是 HashiCorp
公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案,Consul
的方案更“一站式”,内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value
存储、多数据中心方案,不再需要依赖其他工具(比如 ZooKeeper
等)。使用起来也较 为简单。Consul
使用 Go 语言
编写,因此具有天然可移植性(支持Linux
、windows
和Mac OS X
);安装包仅包含一个可执行文件,方便部署,与 Docker
等轻量级容器可无缝配合。
3.2 Consul安装(虚拟机模拟linux操作)
查看所有docker
镜像
docker images
复制代码
拉取Consul
镜像
docker pull consul # 默认拉取latest
复制代码
可以再次查看镜像已经存在Consul
了
启动一个Consul
容器
docker run -d -p 8500:8500 --restart=always --name=consul consul:latest agent -server -bootstrap -ui -node=1 -client='0.0.0.0'
复制代码
查看启动的容器
浏览器访问安装机器的8500
端口
http://ip:8500
复制代码
跳转到如下页面说明安装成功
4 服务注册
接下来我们开发一个简单的服务注册到注册中心。
4.1 创建maven项目
新建一个spring_cloud_demos
项目并创建service_provider
模块,目录结构如下
4.2 引入依赖
在父项目中引入spring-boot-starter-parent
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
</parent>
复制代码
最终如下:
在service_provider中引入Consul
依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
复制代码
最终如下:
4.3 配置文件
server:
port: 8001 #服务端口
spring:
application:
name: service-provider #服务名
cloud:
consul:
host: 192.168.184.128 #注册中心地址
port: 8500 #注册中心端口
discovery:
service-name: ${spring.application.name} #注册中心中该服务的服务名
复制代码
4.4 编写代码
4.4.1 启动类
/**
* Copyright (c) 2022 itmentu.com, All rights reserved.
*
* @Author: yang
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceProvicerApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceProvicerApplication.class, args);
}
}
复制代码
代码说明:
1:@EnableDiscoveryClient表示发现注册中心,向注册中心注册服务
2:@SpringBootApplication见springboot章节
复制代码
4.4.2 接口编写
/**
* Copyright (c) 2022 itmentu.com, All rights reserved.
*
* @Author: yang
*/
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello!";
}
}
复制代码
4.4.3 运行启动类
运行后控制台看到如下内容说明启动成功:
同时查看注册中心页面中该服务已经注册成功
5 服务调用
5.1 创建子模块service_consumer
5.2 引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
复制代码
5.3 配置文件
server:
port: 8001 #服务端口
spring:
application:
name: service-provider #服务名
cloud:
consul:
host: 192.168.184.128 #注册中心地址
port: 8500 #注册中心端口
discovery:
service-name: ${spring.application.name} #注册中心中该服务的服务名
register: false #不注册到注册中心
复制代码
说明:
1:由于消费者不需要注册到注册中心,所以spring.cloud.consul.discovery.register为false
复制代码
5.4 编写代码
5.4.1 启动类
/**
* Copyright (c) 2022 itmentu.com, All rights reserved.
*
* @Author: yang
*/
@SpringBootApplication
public class ServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumerApplication.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
复制代码
代码说明:
1:注册一个RestTemplate到spring容器中以便使用
复制代码
5.4.2 接口编写
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/hello")
public String hello(){
//1、获取注册中心中注册的service-provider实例列表
List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances("service-provider");
//2、获取实例
ServiceInstance serviceInstance = serviceInstanceList.get(0);
//3、根据实例的信息拼接的请求地址
String url = serviceInstance.getUri()+ "/hello";
//4、发送请求
return restTemplate.getForObject(url,String.class);
}
}
复制代码
代码说明:
1:DiscoveryClient用于获取注册中心中对应服务的实例
2:serviceInstance.getUri()表示实例中的地址包括ip端口
3:RestTemplate用于进行rest方式的http请求
复制代码
5.4.3 运行启动类并访问接口
浏览器访问
http://localhost:8002/consumer/hello
复制代码
可以看到
说明我们已经成功通过consumer
访问到了service_provider
的/hello接口
并响应数据