自定义ribbon负载均衡策略

匿名 (未验证) 提交于 2019-12-03 00:27:02

虽然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负载均衡原理分析,敬请期待,,,,,,








标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!