服务治理

服务治理

1.注册中心原理

服务治理中有三个角色:

  • 服务提供者:暴露服务接口,供其他服务调用
  • 服务调用者:调用其他服务提供的接口
  • 注册中心:记录并监控微服务各实例状态,推送服务变更信息

解决了哪些问题

  • 服务的调用者不知道该调用谁,只需要找到注册中心,他就会告诉你,额日期额还能告诉你一堆让你挑(==负载均衡==)
    c43301e60c793e840b9c2d3a9b785eb430e0ef49.png
  • ==有的服务挂了呢==,服务(微服务)提供者不仅要注册到注册中心,还要与注册中心之间形成心跳续约(定期向注册中心发请求,证明我还活着),如果不跳了,注册中心也会把你从这个服务列表中去掉,注册中心会推送变更。
    f9dd8b35013e374d7b8fbe92af56a17419416c0a.png

注册中心原理总结

消费者如何得知服务状态变更?

  • 服务提供者通过心跳机制向注册中心报告自己的健康状态,当心跳异常时注册中心会将异常服务剔除,并通知订阅了该服务的消费者
    当提供者有多个实例时,消费者该选择哪一个?
  • 消费者可以通过负载均衡算法,从多个实例中选择一个
    当然了,自己实现注册中心还是有难度的,我们不需要自己实现,因为有很多框架已经为我们实现了==Nacos注册中心==

2.Nacos注册中心

2.1Nacos组件

他作为一个注册中心,肯定是一个独立的服务对不对,将来我们的微服务就会关联向他去注册自己。
我们用Docker部署

  • 首先下载安装nacos镜像
  • 部署
1
2
3
4
5
6
7
8
docker run -d \
--name nacos \
--env-file ./nacos/custom.env \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
--restart=always \
nacos/nacos-server:v2.1.0-slim

2.2服务注册

步骤:

  1. 引入nacos依赖
1
2
3
4
5
<!--nacos 服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  1. 配置nacos地址
1
2
3
4
5
6
spring:
application:
name: item-service # 服务名称
cloud:
nacos:
server-addr: 192.168.150.101:8848 # nacos地址

2.2 服务发现

步骤:

  1. 引入nacos discovery依赖
  2. 配置nacos地址
  3. 服务发现(需要去nacos获取服务列表)nacos提供了一个API DiscoveryClient
1
2
3
4
5
6
7
8
9
10
11
private final DiscoveryClient discoveryClient;

private void handleCartItems(List<CartVO> vos) {
// 1.根据服务名称,拉取服务的实例列表
List<ServiceInstance> instances = discoveryClient.getInstances("item-service");
// 2.负载均衡,挑选一个实例
ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size()));
// 3.获取实例的IP和端口
URI uri = instance.getUri();
// ... 略
}

好的以下是完成上一期使用写死的域名进行补充:

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
//2.1 根据服务名称获取服务的实例列表  
List<ServiceInstance> instances = discoveryClient.getInstances("item-service");
if (CollUtils.isEmpty(instances)){
return;
}
//2.2 手写负载均衡,从实例列表中随机选择一个服务实例
ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size()));
URI uri = instance.getUri();

//2.3 利用RestTemplate发起http请求, 得到http响应
ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
uri + "/items?ids={ids}",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<ItemDTO>>() {
},
Map.of("ids", CollUtil.join(itemIds, ","))
);
//2.3 解析这个响应
if (!response.getStatusCode().is2xxSuccessful()){
// 查询失败,直接结束
return;
}
List<ItemDTO> items = response.getBody();
if (CollUtils.isEmpty(items)) {
return;
}