Ribbon细粒度配置
1、java代码配置
单独建包,不然会产生spring父子上下文重叠,导致该配置为全局配置
package configuration;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author: yangchun
* @description:
* @date: Created in 2020-02-19 7:49
*/
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
}
package com.fj.xiaofeiyang.pay.api.configuration;
import configuration.RibbonConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Configuration;
/**
* @author: yangchun
* @description:
* @date: Created in 2020-02-19 7:51
*/
@RibbonClient(name = "pay",configuration = RibbonConfiguration.class)
public class PayRibbonConfiguration {
}
2、配置文件配置
pay:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
3、最佳实践总结
| 配置方式 | 优点 | 缺点 |
| 代码配置 | 基于代码,更加灵活 | 有小坑(父子上下文),线上修改得重新打包、发包 |
| 属性配置 | 易上手,配置更加直观,线上修改无需重新打包发布,优先级更高 | 极端场景下没有代码配置灵活 |
尽量使用属性配置,属性配置不了采用代码配置,属性配置实现不了的采用代码配置。
4、全局配置
1、让前面的configuration包可以被应用扫描到,让父子上下文重叠
2、第二种如下
package com.fj.xiaofeiyang.pay.api.configuration;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
/**
* @author: yangchun
* @description:
* @date: Created in 2020-02-19 7:51
*/
@RibbonClients(defaultConfiguration = configuration.RibbonConfiguration.class)
public class RibbonConfiguration {}
5、支持的配置项
| 接口 | 作用 | 默认值 |
| IClientConfig | 读取配置 | DefaultClientConfigImpl |
| IRule | 负载均衡规则,选择实例 | ZoneAvoidanceRule |
| IPing | 筛选Ping不通的实例 | DummyPing |
| ServerList<Server> | 交给Ribbon的实例列表 | Ribbon:ConfigurationBasedServerList,Spring Cloud Alibaba :NacosServerList |
| ServerListFilter<Server> | 过滤掉不符合条件的实例 | ZonePreferenceServerListFilter |
| ILoadBalancer | Ribbon的入口 | ZoneAwareLoadBalancer |
| ServerListUpdater | 更新交给Ribbon的List的策略 | PollingServerListUpdater |
java代码配置如下
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
属性配置如下
<clientName>.ribbon.如下属性:
NFLoadBalancerClassName:ILoaderBalancer实现类
NFLoadBalancerRuleClassName:IRule实现类
NFLoadBalancerPingClassName:IPing实现类
NIWSServerListClassName:ServerList实现类
NIWSServerListFilterClassName:ServerListFilter实现类
6、ribbon开启饥饿加载
ribbon:
eager-load:
enabled: true
clients: pay
7、扩展ribbon支持权重选择
spring cloud commons --定义了标准
spring cloud loadbalancer --没有定义权重

先将两个服务实例权重进行修改,
public class NacosWeightRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
@Override
public Server choose(Object key) {
BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer)this.getLoadBalancer();
String name = baseLoadBalancer.getName();
NamingService nameingService = nacosDiscoveryProperties.namingServiceInstance();
try {
Instance instance= null;
instance = nameingService.selectOneHealthyInstance(name);
return new NacosServer(instance);
} catch (NacosException e) {
return null;
}
}
}
然后采用属性
pay:
ribbon:
NFLoadBalancerRuleClassName: com.fj.xiaofeiyang.pay.api.configuration.NacosWeightRule
配置的方式
扩展同一个集群下的服务器实例同时选择
package com.fj.xiaofeiyang.pay.api.configuration;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.core.Balancer;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author: yangchun
* @description:
* @date: Created in 2020-02-19 9:09
*/
public class NacosClusterRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
@Override
public Server choose(Object key) {
BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer)this.getLoadBalancer();
String name = baseLoadBalancer.getName();
String clusterName = nacosDiscoveryProperties.getClusterName();
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
try {
List<Instance> instances= namingService.selectInstances(name,true);
List<Instance> sameClusterInstances = instances.stream().filter(instance -> Objects.equals(instance.getClusterName(),clusterName))
.collect(Collectors.toList());
List<Instance> instancesToBchosen = new ArrayList<>();
if(CollectionUtils.isEmpty(sameClusterInstances)){
instancesToBchosen = instances;
}else {
instancesToBchosen = sameClusterInstances;
}
Instance instance= ExtendBalancer.getHostByRandomWeight2(instancesToBchosen);
return new NacosServer(instance);
} catch (NacosException e) {
return null;
}
}
}
class ExtendBalancer extends Balancer{
public static Instance getHostByRandomWeight2(List<Instance> instances){
return getHostByRandomWeight(instances);
}
}
然后采用属性
pay:
ribbon:
NFLoadBalancerRuleClassName: com.fj.xiaofeiyang.pay.api.configuration.NacosClusterRule
扩展通过元数据版本来实现
package com.fj.xiaofeiyang.pay.api.configuration;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author: yangchun
* @description:
* @date: Created in 2020-02-19 9:09
*/
public class NacosVersionRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
@Override
public Server choose(Object key) {
BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer)this.getLoadBalancer();
String name = baseLoadBalancer.getName();
String targetVesion = nacosDiscoveryProperties.getMetadata().get("target-version");
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
try {
List<Instance> instances= namingService.selectInstances(name,true);
List<Instance> sameClusterInstances = instances.stream().filter(instance -> Objects.equals(instance.getMetadata().get("version"),targetVesion))
.collect(Collectors.toList());
List<Instance> instancesToBchosen = new ArrayList<>();
if(CollectionUtils.isEmpty(sameClusterInstances)){
instancesToBchosen = instances;
}else {
instancesToBchosen = sameClusterInstances;
}
Instance instance= ExtendBalancer.getHostByRandomWeight2(instancesToBchosen);
return new NacosServer(instance);
} catch (NacosException e) {
return null;
}
}
}

浙公网安备 33010602011771号