"服务调用者如何选择服务目标实例"
核心原理
服务注册
- 服务目标者 注册实例 到注册中心
实例订阅
- 服务调用者通过注册中心 订阅服务目标者,将服务目标者的健康实例推送给消费者
健康检查
- 注册中心定期对服务目标者提供健康检查(TCP端口、HTTP接口),并剔除不健康的,不可用的实例
负载均衡调用
-
消费者发起调用时,Nacos Client内置的负载均衡,按算法选择一个实例发起Http调用
-
默认采用负载均衡算法:轮询
Nacos健康检查机制
-
默认启用的:默认
5秒一次心跳包,服务中心超过15秒没收到心跳则说明不健康,30秒没收到就剔除 -
服务端主动监测:服务中心向目标实例发起检测请求(TCP/HTTP),未响应就为故障
需要在服务目标者的application.yml中配置数据
XML
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
metadata:
nacos.health.check.url: /actuator/health # Spring Boot Actuator 健康检查接口
nacos.health.check.interval: 5000 # 检测间隔 5 秒
nacos.health.check.timeout: 3000 # 超时时间 3 秒
实操
- 依赖
java
<!-- Nacos 服务发现依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Spring Cloud LoadBalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
- 注入LoadBalanceClient
java
//@Autowired
//DiscoveryClient discoveryClient;
@Autowired
RestTemplate restemplate;
@Autowired
LoadBalancerClient loadBalancerClient;
- 然后给远程调用更换成LoadBalancerClient;
java
ServiceInstance choose = loadBalancerClient.choose("service-product");
String url = "http://"+choose.getHost()+":"+choose.getPort()+"/product/"+productId;
Product product = restTemplate.getForObject(url,Product.class);
注解式负载均衡
基于SpringCloud LoadBalancer
@LoadBalanced
只需要给RestTemplate加上这个注解(默认采用负载均衡算法:轮询)
java
@Configuration
public class RestTemplateConfig {
// @LoadBalanced:启用负载均衡,自动从Nacos获取实例并分发流量
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
这样就可以
java
//直接调用服务目标者
String url = "http://service-product/product"+productId;
//service-product会被动态切换
Product product - restemplate.getForObject(url,Product.class);
如果注册中心宕机了,还能使用负载均衡吗
由于有实例缓存
如果调用过一次注册中心的实例列表,就不会再去注册中心,可以使用负载均衡
但是如果没有调用过一次注册中心的实例列表,就不能使用负载均衡了
