当前位置:首页 >> 核电技术聚变聚能设备 >> 【ribbon】Ribbon的负载均衡和扩展功能,a390(ribbon支持的负载均衡算法有哪些)

【ribbon】Ribbon的负载均衡和扩展功能,a390(ribbon支持的负载均衡算法有哪些)

cpugpu芯片开发光刻机 核电技术聚变聚能设备 1
文件名:【ribbon】Ribbon的负载均衡和扩展功能,a390 【ribbon】Ribbon的负载均衡和扩展功能 Ribbon的核心接口

参考:org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration

IClientConfig:Ribbon的客户端配置,默认采用DefaultClientConfigImpl实现。IRule:Ribbon的负载均衡策略,默认采用ZoneAvoidanceRule实现,该策略能够在多区域环境下选出最佳区域的实例进行访问。IPing:Ribbon的实例检查策略,默认采用DummyPing实现,该检查策略是一个特殊的实现,实际上它并不会检查实例是否可用,而是始终返回true,默认认为所有服务实例都是可用的。ServerList:服务实例清单的维护机制,默认采用ConfigurationBasedServerList实现。ServerListFilter:服务实例清单过滤机制,默认采ZonePreferenceServerListFilter,该策略能够优先过滤出与请求方处于同区域的服务实例。ILoadBalancer:负载均衡器,默认采用ZoneAwareLoadBalancer实现,它具备了区域感知的能力。 Ribbon负载均衡策略

RandomRule:随机选择一个Server。RetryRule:对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的server。RoundRobinRule:轮询选择,轮询index,选择index对应位置的Server。AvailabilityFilteringRule:过滤掉一直连接失败的被标记为circuit tripped的后端Server,并过滤掉那些高并发的后端Server或者使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就是检查status里记录的各个Server的运行状态。BestAvailableRule:选择一个最小的并发请求的Server,逐个考察Server,如果Server被tripped了,则跳过。WeightedResponseTimeRule:根据响应时间加权,响应时间越长,权重越小,被选中的可能性越低。ZoneAvoidanceRule:默认的负载均衡策略,即复合判断Server所在区域的性能和Server的可用性选择Server,在没有区域的环境下,类似于轮询NacosRule: 优先调用同一集群的实例,基于随机权重 修改默认负载均衡策略 全局配置

全局配置:所有调用的微服务一律使用指定的负载均衡策略,只需要向容器中注入IRule实例即可。

package com.morris.user.config;import com.alibaba.cloud.nacos.ribbon.NacosRule;import com.netflix.loadbalancer.IRule;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class RibbonConfig {@Beanpublic IRule ribbonRule() {// 指定使用Nacos提供的负载均衡策略(优先调用同一集群的实例,基于随机权重)return new NacosRule();}} 局部配置

局部配置:可以在配置文件中调用指定微服务时,使用对应的负载均衡策略。

# 被调用的微服务名order-service:ribbon:# 指定使用Nacos提供的负载均衡策略(优先调用同一集群的实例,基于随机&权重)NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule 自定义负载均衡策略

通过实现IRule接口可以自定义负载策略,主要的选择服务逻辑在choose方法中。

实现基于Nacos权重的负载均衡策略:

package com.morris.user.config;import com.alibaba.cloud.nacos.NacosDiscoveryProperties;import com.alibaba.cloud.nacos.NacosServiceManager;import com.alibaba.cloud.nacos.ribbon.NacosServer;import com.alibaba.nacos.api.exception.NacosException;import com.alibaba.nacos.api.naming.NamingService;import com.alibaba.nacos.api.naming.pojo.Instance;import com.netflix.client.config.IClientConfig;import com.netflix.loadbalancer.AbstractLoadBalancerRule;import com.netflix.loadbalancer.DynamicServerListLoadBalancer;import com.netflix.loadbalancer.Server;import lombok.extern.slf4j.Slf4j;import javax.annotation.Resource;@Slf4jpublic class NacosRandomWithWeightRule extends AbstractLoadBalancerRule {@Resourceprivate NacosServiceManager nacosServiceManager;@Resourceprivate NacosDiscoveryProperties nacosDiscoveryProperties;@Overridepublic Server choose(Object key) {DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();String serviceName = loadBalancer.getName();NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());try {//nacos基于权重的算法Instance instance = namingService.selectOneHealthyInstance(serviceName);return new NacosServer(instance);} catch (NacosException e) {log.error("获取服务实例异常:{}", e.getMessage());e.printStackTrace();}return null;}@Overridepublic void initWithNiwsConfig(IClientConfig iClientConfig) {}}

可以将NacosRandomWithWeightRule按照上面的全局配置或者局部配置。

饥饿加载

在进行服务调用的时候,如果网络情况不好,第一次调用会超时。Ribbon默认懒加载,意味着只有在发起调用的时候才会创建客户端。

应用启动后第一次请求会有2s左右的延时,如果此时有大量请求进来就会抛出大量异常。

2023-07-21 16:50:37.718 INFO 20488 --- [nio-8030-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'2023-07-21 16:50:37.718 INFO 20488 --- [nio-8030-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'2023-07-21 16:50:37.733 INFO 20488 --- [nio-8030-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 15 ms2023-07-21 16:50:39.332 INFO 20488 --- [nio-8030-exec-1] c.netflix.loadbalancer.BaseLoadBalancer : Client: order-service instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=order-service,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null2023-07-21 16:50:39.346 INFO 20488 --- [nio-8030-exec-1] c.n.l.DynamicServerListLoadBalancer : Using serverListUpdater PollingServerListUpdater2023-07-21 16:50:39.534 INFO 20488 --- [nio-8030-exec-1] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client order-service initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=order-service,current list of Servers=[2.0.0.1:8020],Load balancer stats=Zone stats: {unknown=[Zone:unknown;Instance count:1;Active connections count: 0;Circuit breaker tripped count: 0;Active connections per server: 0.0;]},Server stats: [[Server:2.0.0.1:8020;Zone:UNKNOWN;Total Requests:0;Successive connection failure:0;Total blackout seconds:0;Last connection made:Thu Jan 01 08:00:00 CST 1970;First connection made: Thu Jan 01 08:00:00 CST 1970;Active Connections:0;total failure count in last (1000) msecs:0;average resp time:0.0;90 percentile resp time:0.0;95 percentile resp time:0.0;min resp time:0.0;max resp time:0.0;stddev resp time:0.0]]}ServerList:com.alibaba.cloud.nacos.ribbon.NacosServerList@fb090e

开启饥饿加载,解决第一次调用慢的问题:

ribbon:eager-load:enabled: trueclients: order-service

参数说明:

ribbon.eager-load.enabled:开启ribbon的饥饿加载模式ribbon.eager-load.clients:指定需要饥饿加载的服务名,也就是你需要调用的服务,如果有多个服务,则用逗号隔开

看下效果,在启动过程中就已经初始化连接了:

2023-07-21 16:54:18.480 INFO 22040 --- [ main] com.morris.user.UserServiceApplication : Started UserServiceApplication in 6.846 seconds (JVM running for 8.265)2023-07-21 16:54:19.254 INFO 22040 --- [ main] c.netflix.loadbalancer.BaseLoadBalancer : Client: order-service instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=order-service,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null2023-07-21 16:54:19.260 INFO 22040 --- [ main] c.n.l.DynamicServerListLoadBalancer : Using serverListUpdater PollingServerListUpdater2023-07-21 16:54:19.286 INFO 22040 --- [ main] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client order-service initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=order-service,current list of Servers=[2.0.0.1:8020],Load balancer stats=Zone stats: {unknown=[Zone:unknown;Instance count:1;Active connections count: 0;Circuit breaker tripped count: 0;Active connections per server: 0.0;]},Server stats: [[Server:2.0.0.1:8020;Zone:UNKNOWN;Total Requests:0;Successive connection failure:0;Total blackout seconds:0;Last connection made:Thu Jan 01 08:00:00 CST 1970;First connection made: Thu Jan 01 08:00:00 CST 1970;Active Connections:0;total failure count in last (1000) msecs:0;average resp time:0.0;90 percentile resp time:0.0;95 percentile resp time:0.0;min resp time:0.0;max resp time:0.0;stddev resp time:0.0]]}ServerList:com.alibaba.cloud.nacos.ribbon.NacosServerList@432469 NacosRule源码分析

com.alibaba.cloud.nacos.ribbon.NacosRule#choose

@Overridepublic Server choose(Object key) {try {String clusterName = this.nacosDiscoveryProperties.getClusterName();String group = this.nacosDiscoveryProperties.getGroup();DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();String name = loadBalancer.getName();// 获取NamingService,在我们的代码中也可以这么使用NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());// 筛选出同一个group的实例,不同group之间不能通讯List<Instance> instances = namingService.selectInstances(name, group, true);if (CollectionUtils.isEmpty(instances)) {LOGGER.warn("no instance in service {}", name);return null;}List<Instance> instancesToChoose = instances;if (StringUtils.isNotBlank(clusterName)) {// 找出同一个集群的节点List<Instance> sameClusterInstances = instances.stream().filter(instance -> Objects.equals(clusterName,instance.getClusterName())).collect(Collectors.toList());if (!CollectionUtils.isEmpty(sameClusterInstances)) {instancesToChoose = sameClusterInstances;}else {LOGGER.warn("A cross-cluster call occurs,name = {}, clusterName = {}, instance = {}",name, clusterName, instances);}}// 带权重的随机选择一个节点Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToChoose);return new NacosServer(instance);}catch (Exception e) {LOGGER.warn("NacosRule error", e);return null;}}

NacosRule是AlibabaNacos自己实现的一个负载均衡策略,可以在nacos平台中根据自定义权重进行访问。

基于Nacos元数据的版本控制自定义负载均衡

实际项目,我们可能还会有这样的需求:

一个微服务在线上可能多版本共存,且多个版本的微服务并不兼容。使用Nacos的自定义元数据,可以实现微服务的版本控制。

配置文件的格式: spring.cloud.nacos.discovery.metadata.{key}={value}

当前配置的版本: spring.cloud.nacos.discovery.metadata.version=V1

package com.morris.user.config;import com.alibaba.cloud.nacos.NacosDiscoveryProperties;import com.alibaba.cloud.nacos.NacosServiceManager;import com.alibaba.cloud.nacos.ribbon.ExtendBalancer;import com.alibaba.cloud.nacos.ribbon.NacosServer;import com.alibaba.nacos.api.exception.NacosException;import com.alibaba.nacos.api.naming.NamingService;import com.alibaba.nacos.api.naming.pojo.Instance;import com.netflix.client.config.IClientConfig;import com.netflix.loadbalancer.AbstractLoadBalancerRule;import com.netflix.loadbalancer.BaseLoadBalancer;import com.netflix.loadbalancer.Server;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang.StringUtils;import javax.annotation.Resource;import java.util.List;import java.util.stream.Collectors;@Slf4jpublic class ClusterMetaDataRibbonRule extends AbstractLoadBalancerRule {@Resourceprivate NacosDiscoveryProperties nacosDiscoveryProperties;@Resourceprivate NacosServiceManager nacosServiceManager;@Overridepublic void initWithNiwsConfig(IClientConfig iClientConfig) {}@Overridepublic Server choose(Object o) {log.info("-------key: {}", o);// 获取当前服务的集群名称String currentClusterName = nacosDiscoveryProperties.getClusterName();// 获取当前版本String currentVersion = nacosDiscoveryProperties.getMetadata().get("version");// 获取被调用的服务的名称BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) getLoadBalancer();String serviceName = baseLoadBalancer.getName();// 获取nacos clinet的服务注册发现组件的apiNamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());try {// 获取所有被调用服务List<Instance> allInstances = namingService.getAllInstances(serviceName);// 过滤出相同版本且相同集群下的所有服务List<Instance> sameVersionAndClusterInstances = allInstances.stream().filter(x -> StringUtils.equalsIgnoreCase(x.getMetadata().get("version"), currentVersion)&& StringUtils.equalsIgnoreCase(x.getClusterName(), currentClusterName)).collect(Collectors.toList());Instance chooseInstance;if(sameVersionAndClusterInstances.isEmpty()) {// 过滤出所有相同版本的服务List<Instance> sameVersionInstances = allInstances.stream().filter(x -> StringUtils.equalsIgnoreCase(x.getMetadata().get("version"), currentVersion)).collect(Collectors.toList());if(sameVersionInstances.isEmpty()) {log.info("跨集群调用找不到对应合适的版本当前版本为:currentVersion:{}",currentVersion);throw new RuntimeException("找不到相同版本的微服务实例");}else {// 随机权重chooseInstance = ExtendBalancer.getHostByRandomWeight2(sameVersionInstances);log.info("跨集群同版本调用--->当前微服务所在集群:{},被调用微服务所在集群:{},当前微服务的版本:{},被调用微服务版本:{},Host:{},Port:{}",currentClusterName, chooseInstance.getClusterName(), chooseInstance.getMetadata().get("current-version"),chooseInstance.getMetadata().get("current-version"), chooseInstance.getIp(), chooseInstance.getPort());}}else {chooseInstance = ExtendBalancer.getHostByRandomWeight2(sameVersionAndClusterInstances);log.info("同集群同版本调用--->当前微服务所在集群:{},被调用微服务所在集群:{},当前微服务的版本:{},被调用微服务版本:{},Host:{},Port:{}",currentClusterName, chooseInstance.getClusterName(), chooseInstance.getMetadata().get("version"),chooseInstance.getMetadata().get("current-version"), chooseInstance.getIp(), chooseInstance.getPort());}return new NacosServer(chooseInstance);} catch (NacosException e) {log.error("error,", e);return null;}}}
协助本站SEO优化一下,谢谢!
关键词不能为空
同类推荐
«    2025年12月    »
1234567
891011121314
15161718192021
22232425262728
293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接