Nacos- 负载均衡和服务实例的权重配置
1.Nacos-NacosRule负载均衡
准备二个微服务项目 order(消费者)、payment(生产者)。
NacosRule负载均衡策略
- 优先选择同集群服务实例列表
- 本地集群找不到提供者,才去其它集群寻找,并且会报警告。
- 确定了可用实例列表后,再采用随机负载均衡挑选实例。
1.修改order中的application.yml,设置集群为shanghai:
1 spring: 2 application: 3 name: payment 4 cloud: 5 nacos: 6 server-addr: 127.0.0.1:8848 # nacos服务地址 7 discovery: 8 cluster-name: shanghai #payment服务在上海集群,order使用默认集群(DEFAULT)在调用payment服务优先选择DEFAULT集群,如果DEFAULT集群宕机的情况下才会找到上海集群服务实例列表
2.然后在order服务中设置负载均衡的IRule为NacosRule,这个规则优先会寻找与自己同集群的服务,局部配置 只针对 payment这个服务生效:
1 payment: 2 ribbon: 3 NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
跨集群调用预警信息:
2022-01-18 13:25:44.211 [http-nio-8080-exec-4] [WARN ][com.alibaba.cloud.nacos.ribbon.NacosRule] - A cross-cluster call occurs,name = payment, clusterName = DEFAULT, instance = [Instance{instanceId='null', ip='172.17.120.97', port=8082, weight=1.0, healthy=true, enabled=true, ephemeral=true, clusterName='shanghai', serviceName='DEFAULT_GROUP@@payment', metadata={preserved.register.source=SPRING_CLOUD}}]
2.Nacos-服务实例的权重配置
使用场景:服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。
Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高,实例的权重控制。
- Nacos控制台可以设置实例的权重值,0~1之间
- 同集群内的多个实例,权重越高被访问的频率越高
- 权重设置为0则完全不会被访问
举栗子:把 payment:8081服务权重调整为0,此时payment:8081服务不接收用户请求,这时做停机操作对用户是无感知操作。我们可以做版本升级,升级结束后权重调小点(如:0.01),对小部分用户开放等没问题再把权重调大。这样操作对用户是无感知的,平滑升级非常优雅。
设置权重负载均衡:
在Nacos控制台可以设置实例的权重值,如下图:
设置权重:
将实例权重设置为0,该实例将不再接收用户请求。当实例权重设置为0.01,被访问到的频率就大大的减小了。
注意:默认情况下只在Nacos控制台修改权重配置是没有作用的。因为Nacos 的负载均衡底层是基于Ribbon实现的。而Ribbon默认的rule是轮询,在没有设置的情况下默认规则是轮询策略。如果想使用结合Nacos后台权重设置的策略,需要在服务的配置文件(yml)中配置NacosRule规则(或者将NacosRule 注册成为Bean),替换默认的 Rule即可。
3.自定义负载均衡策略
1 package com.order.nacos.config; 2 3 import com.alibaba.nacos.api.exception.NacosException; 4 import com.alibaba.nacos.api.naming.pojo.Instance; 5 import com.netflix.client.config.IClientConfig; 6 import com.netflix.loadbalancer.AbstractLoadBalancerRule; 7 import com.netflix.loadbalancer.DynamicServerListLoadBalancer; 8 import com.netflix.loadbalancer.Server; 9 import lombok.extern.slf4j.Slf4j; 10 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties; 12 import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer; 13 14 /** 15 * 基于Nacos权重的负载均衡 16 * 17 * @Author mingtian 18 * @create 2022/01/18 14:54 19 */ 20 @Slf4j 21 public class NacosWeightLoadBalancerRule extends AbstractLoadBalancerRule { 22 23 @Autowired 24 private NacosDiscoveryProperties nacosDiscoveryProperties; 25 26 @Override 27 public void initWithNiwsConfig(IClientConfig iClientConfig) { 28 // 读取配置文件,并初始化NacosWeightLoadBalancerRule 29 } 30 31 @Override 32 public Server choose(Object o) { 33 DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer(); 34 // 请求的微服务名称 35 String applicationName = loadBalancer.getName(); 36 try { 37 // nacos 通过基于权重的负载均衡算法,算出一个健康的服务实例以供调用 38 Instance instance = nacosDiscoveryProperties.namingServiceInstance().selectOneHealthyInstance(applicationName); 39 return new NacosServer(instance); 40 } catch (NacosException e) { 41 log.error("获取服务实例异常:{}", e.getMessage()); 42 } 43 return null; 44 } 45 }
4.局部配置与全局配置区别
4.1 局部配置
调用指定服务提供的服务时,使用基于Nacos权重的负载均衡算法,针对于单个服务的负载均衡策略配置。
order服务yml配置:
# 被调用的微服务名 payment: ribbon: # 指定使用Nacos提供的基于权重的负载均衡 NFLoadBalancerRuleClassName: com.order.nacos.NacosWeightLoadBalancerRule
4.2 全局配置
调用其他微服务,一律使用基于Nacos权重的负载均衡算法
1 package com.order.nacos.config; 2 3 import com.netflix.loadbalancer.IRule; 4 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.Configuration; 6 7 @Configuration 8 public class RibbonConfiguration { 9 10 @Bean 11 public IRule ribbonRule() { 12 return new NacosWeightLoadBalancerRule(); 13 } 14 15 }