一、什么要进行负载均衡
负载均衡就是为避免所有请求都打到一个服务器上面,导致服务器异常儿产生的服务不可问题。
下面我们就来自定负载均衡的策略,我这边实现的只有一下三种,但是实际上根据业务需求的不同会产生各种均衡策略:
- 根据权重随机选择一个实例
- 优先选择同集群
- 优先选择同版本同集群的示例(金丝雀发布—实现同版本同集群优先负载均衡策略)
二、自定义负载均衡策略
这里我先将我的目录放在这里,下面是各种实现

第一步:自定义一个负载均衡的配置类
这里使用我们自定义的全局配置类
1 2 3 4 5 6 7 8 9 10 11 12
| package com.sy.springcloud.config.ribbon;
import com.sy.ribbon.GlobalRibbonConfig; import org.springframework.cloud.netflix.ribbon.RibbonClients; import org.springframework.context.annotation.Configuration;
@Configuration @RibbonClients(defaultConfiguration = GlobalRibbonConfig.class) public class CustomeRibbonConfig { }
|
第二步:在我们的全局配置类中配置我们想要使用的自定义的负载均衡策略
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
| package com.sy.ribbon;
import com.netflix.loadbalancer.IRule; import com.sy.springcloud.config.ribbon.rule.TheSameClusterPriorityRule; import com.sy.springcloud.config.ribbon.rule.TheSameClusterPriorityWithVersionRule; import com.sy.springcloud.config.ribbon.rule.WeightedBalancerRule; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component;
@Component public class GlobalRibbonConfig {
@Bean public IRule iRule() { return new WeightedBalancerRule(); }
}
|
第三步:自定义我们的负载均衡策略
第1种类型:根据权重随机选择一个实例
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| package com.sy.springcloud.config.ribbon.rule;
import com.alibaba.cloud.nacos.NacosServiceManager; import com.alibaba.cloud.nacos.ribbon.NacosServer; 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.springframework.beans.factory.annotation.Autowired;
@Slf4j public class WeightedBalancerRule extends AbstractLoadBalancerRule {
@Autowired private NacosServiceManager nacosServiceManager; @Override public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
@Override public Server choose(Object o) { try { log.info("key:{}",o); BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer(); String serviceName = loadBalancer.getName(); NamingService namingService = nacosServiceManager.getNamingService();
Instance instance = namingService.selectOneHealthyInstance(serviceName);
return new NacosServer(instance); } catch (Exception e) { e.printStackTrace(); } return null; } }
|
第2种类型:优先选择同集群
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| package com.sy.springcloud.config.ribbon.rule;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; import com.alibaba.cloud.nacos.NacosServiceManager; import com.alibaba.cloud.nacos.ribbon.NacosServer; 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.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors;
@Slf4j public class TheSameClusterPriorityRule extends AbstractLoadBalancerRule {
@Autowired private NacosServiceManager nacosServiceManager;
@Autowired private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
@Override public Server choose(Object o) { try { String clusterName = nacosDiscoveryProperties.getClusterName(); log.info("当前集群名称:{}", clusterName); BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer(); String serviceName = loadBalancer.getName(); log.info("目标服务的实例名称:{}", serviceName); NamingService namingService = nacosServiceManager.getNamingService(); List<Instance> allInstance = namingService.getAllInstances(serviceName);
List<Instance> sameClusterInstanceList; sameClusterInstanceList = allInstance.stream().filter(instance -> instance.getClusterName().equals(clusterName)).collect(Collectors.toList()); log.info("统计群的服务实例:{}", sameClusterInstanceList); Instance toBeChooseInstance; if (sameClusterInstanceList == null || sameClusterInstanceList.size() == 0) { toBeChooseInstance = WeightedBalancer.chooseInstanceByRandomWeight(allInstance); log.info("跨集群调用---{}", toBeChooseInstance.getPort()); } else { toBeChooseInstance = WeightedBalancer.chooseInstanceByRandomWeight(sameClusterInstanceList); log.info("同集群调用---{}", toBeChooseInstance.getPort()); } return new NacosServer(toBeChooseInstance); } catch (Exception e) { e.printStackTrace(); }
return null; } }
|
这里以及下一种类型会用到一个类,这个类的作用是根据在符合的实例中随机选择一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.sy.springcloud.config.ribbon.rule;
import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.client.naming.core.Balancer;
import java.util.List;
public class WeightedBalancer extends Balancer { public static Instance chooseInstanceByRandomWeight(List<Instance> instanceList) { return getHostByRandomWeight(instanceList); } }
|
第3种类型:同版本同集群优先择负载均衡策略
这个策略也可以叫做金丝雀发布策略:灰度测试的场景下可以使用
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| package com.sy.springcloud.config.ribbon.rule;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties; import com.alibaba.cloud.nacos.NacosServiceManager; import com.alibaba.cloud.nacos.ribbon.NacosServer; 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.springframework.beans.factory.annotation.Autowired;
import java.util.List; import java.util.stream.Collectors;
@Slf4j public class TheSameClusterPriorityWithVersionRule extends AbstractLoadBalancerRule {
@Autowired private NacosServiceManager nacosServiceManager;
@Autowired private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
@Override public Server choose(Object o) { try { String clusterName = nacosDiscoveryProperties.getClusterName(); String version = nacosDiscoveryProperties.getMetadata().get("version"); log.info("当前集群名称:{},服务版本号:{}", clusterName, version); BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer(); String serviceName = loadBalancer.getName(); log.info("目标服务的实例名称:{}", serviceName); NamingService namingService = nacosServiceManager.getNamingService(); List<Instance> allInstance = namingService.getAllInstances(serviceName);
List<Instance> sameVersionInstance; sameVersionInstance = allInstance.stream().filter(instance -> instance.getMetadata().get("version").equals(version)).collect(Collectors.toList());
List<Instance> sameClusterInstanceList; sameClusterInstanceList = sameVersionInstance.stream().filter(instance -> instance.getClusterName().equals(clusterName)).collect(Collectors.toList()); log.info("统计群的服务实例:{}", sameClusterInstanceList); Instance toBeChooseInstance; if (sameClusterInstanceList == null || sameClusterInstanceList.size() == 0) { toBeChooseInstance = WeightedBalancer.chooseInstanceByRandomWeight(sameVersionInstance); log.info("跨集群调用---{}", toBeChooseInstance.getPort()); } else { toBeChooseInstance = WeightedBalancer.chooseInstanceByRandomWeight(sameClusterInstanceList); log.info("同集群调用---{}", toBeChooseInstance.getPort()); } return new NacosServer(toBeChooseInstance); } catch (Exception e) { e.printStackTrace(); }
return null; } }
|
三种配置到这里就完事了,接下来就可以在Nacos中配置权重与版本号进行测试了