一个服务可以有多个实例,例如我们的user-service,可以有:
- 127.0.0.1:8081
- 127.0.0.1:8082
- 127.0.0.1:8083
假如这些实例分布于全国各地的不同机房,例如:
- 127.0.0.1:8081,在上海机房
- 127.0.0.1:8082,在上海机房
- 127.0.0.1:8083,在杭州机房
Nacos就将同一机房内的实例 划分为一个集群。也就是说,userService是服务名称
,一个服务可以由多个服务集群
组成,如杭州集群、上海集群,而每个集群下又可以有多个服务实例
,形成分级模型,如图:
微服务互相访问时,应该尽可能访问 同一集群
下的服务实例,因为处于同一集群下的本地访问速度更快。当本集群内不可用时,才会访问其它集群
。例如:
杭州机房内的orderService应该优先访问同机房的userService,若杭州机房内的的userService服务都不可用了,才会调用上海机房内的userService。
在需要配置集群的服务的application.yml文件中添加一下集群配置:
spring:
cloud:
nacos:
server-addr: localhost:8848 #服务中心地址
discovery:
cluster-name: HZ # 集群名称
重启两个userService实例后,我们可以在nacos控制台看到下面结果:
我们再次复制一个userService启动配置,添加属性(将服务添加到SH集群):
-Dserver.port=8083 -Dspring.cloud.nacos.discovery.cluster-name=SH
启动新配置的userService,我们查看Nacos控制台:
这样,我们就完成了HZ和SH集群的划分。
对于服务的调用,杭州的集群调用杭州自身的服务肯定效率会比调用上海的更高,因此我们对于同一集群下的服务应该优先调用
,从而降低网络延时,提高响应速度。
默认的ZoneAvoidanceRule
并不能实现根据同集群优先来实现负载均衡。因此Nacos中提供了一个NacosRule
的实现,可以优先从同集群中挑选实例
。
1)给order-service配置集群信息
修改order-service的application.yml文件,添加集群配置:
spring:
cloud:
nacos:
server-addr: localhost:8848
discovery:
cluster-name: HZ # 集群名称
2)修改负载均衡规则
修改order-service的application.yml文件,修改负载均衡规则:
userservice:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
配置完毕后,我们重启orderService服务,模拟3次服务调用,查看userService控制台输出:
可以看到8081端口的userService服务并没有任何输出
而端口号为8082的userService服务被调用了一次。
而端口号为8083的userService服务被调用了两次。
回顾上面我们在Nacos管理页面配置的userService集群,8082和8083端口都属于HZ集群,而我们配置的orderService也属于HZ集群,因此优先调用了HZ集群内的userService,而没有调用SH集群的userService。
模拟本集群服务挂掉
我们停掉HZ集群内的userService服务,查看Nacos管理页面:
此时仅有SH集群还处于健康状态,我们对orderService进行访问,让orderService调用userService服务:
可以看到8081的端口进行了一次输出,说明HZ集群内的orderService服务调用了SH集群的userService。我们再查看orderService的控制台输出,可以看到打印了一条警告信息:
06-22 15:58:48:595 WARN 82005 --- [nio-8088-exec-6]
c.alibaba.cloud.nacos.ribbon.NacosRule : A cross-cluster call occurs,name =
userService, clusterName = HZ, instance =
[Instance{instanceId='192.168.159.26#8081#SH#DEFAULT_GROUP@@userService',
ip='192.168.159.26', port=8081, weight=1.0, healthy=true, enabled=true,
ephemeral=true, clusterName='SH',
serviceName='DEFAULT_GROUP@@userService', metadata=
{preserved.register.source=SPRING_CLOUD}}]
该警告提示我们orderService进行了一次跨集群的服务调用,因为HZ集群下的userService服务实例列表为空,无法进行本集群内的服务调用。