虽然ribbon默认为我们提供了多钟负载均衡策略,但有时候我们仍然需要自定义符合自身业务逻辑的规则
使用配置文件的方式:我们只需要在配置文件中添加配置
ribbon.NFLoadBalancerRuleClassName=自定义的负载均衡策略类
其中 serviceId 为具体服务名
这样在调用对应服务时候,就会使用我们自定义的负载策略,很方便
对于该配置文件springcloud是如何解析的呢,接下来我们就分析该配置为何生效
@Bean @ConditionalOnMissingBean public IRule ribbonRule(IClientConfig config) { if (this.propertiesFactory.isSet(IRule.class, name)) { return this.propertiesFactory.get(IRule.class, config, name); } ZoneAvoidanceRule rule = new ZoneAvoidanceRule(); rule.initWithNiwsConfig(config); return rule; }
第一行:判断当前环境是否设置了IRule类
public boolean isSet(Class clazz, String name) { return StringUtils.hasText(getClassName(clazz, name)); }
getClassName 具体实现如下:
public String getClassName(Class clazz, String name) { if (this.classToProperty.containsKey(clazz)) { String classNameProperty = this.classToProperty.get(clazz); String className = environment.getProperty(name + "." + NAMESPACE + "." + classNameProperty); return className; } return null; }
而classToProperty是啥呢
public PropertiesFactory() { classToProperty.put(ILoadBalancer.class, "NFLoadBalancerClassName"); classToProperty.put(IPing.class, "NFLoadBalancerPingClassName"); classToProperty.put(IRule.class, "NFLoadBalancerRuleClassName"); classToProperty.put(ServerList.class, "NIWSServerListClassName"); classToProperty.put(ServerListFilter.class, "NIWSServerListFilterClassName"); }
String className = environment.getProperty(name + "." + NAMESPACE + "." + classNameProperty);
其中 name 为ribbon.client.name 也就是我们服务名,
NAMESPACE Ϊ ribbon
接着看ribbonRule 第二行代码
return this.propertiesFactory.get(IRule.class, config, name);
具体get实现:
public <C> C get(Class<C> clazz, IClientConfig config, String name) { String className = getClassName(clazz, name); if (StringUtils.hasText(className)) { try { Class<?> toInstantiate = Class.forName(className); return (C) instantiateWithConfig(toInstantiate, config); } catch (ClassNotFoundException e) { throw new IllegalArgumentException("Unknown class to load "+className+" for class " + clazz + " named " + name); } } return null; }
这样就很清晰了,最终会根据我们配置的负载策略类全路径 生成对应的实例
怎么处理呢?
结合我们目前项目的处理方式,这里我给出另一条思路
在配置文件中,我们添加一个属性
loadbalanced.services = service-A,service-B
@Configuration @ConditionalOnClass(com.netflix.loadbalancer.ZoneAvoidanceRule.class) public class RibbonLoadbalancerRuleConfiguration implements InitializingBean { private final static Logger log = LoggerFactory.getLogger(RibbonLoadbalancerRuleConfiguration.class); @Value("#{'${loadbalanced.services}'.split(',')}") private List<String> loadbalancedServices; /** * 默认使用切流量的负载均衡策略 */ @Value("${ribbon.NFLoadBalancerRuleClassName}") private String ribbonLoadBancerRule; @Override public void afterPropertiesSet() throws Exception { if (null != loadbalancedServices)) { for (String service : loadbalancedServices)) { String key = service + ".ribbon.NFLoadBalancerRuleClassName"; System.setProperty(key, ribbonLoadBancerRule); } } } }
这样在配置文件中我们只需要配置
ribbon.NFLoadBalancerRuleClassName=自定义负载均衡策略 loadBalancedService=需要使用自定义负载均衡策略的服务
有时间会整理一篇更完整的ribbon负载均衡原理分析,敬请期待,,,,,,
文章来源: 自定义ribbon负载均衡策略