虽然ribbon默认为我们提供了多钟负载均衡策略,但有时候我们仍然需要自定义符合自身业务逻辑的规则

使用配置文件的方式:我们只需要在配置文件中添加配置

serviceId.ribbon.NFLoadBalancerRuleClassName=自定义的负载均衡策略类

其中 serviceId 为具体服务名

这样在调用对应服务时候,就会使用我们自定义的负载策略,很方便

对于该配置文件springcloud是如何解析的呢,接下来我们就分析该配置为何生效

引入关键类 RibbonClientConfiguration

1
2
3
4
5
6
7
8
9
10
    @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类

1
2
3
public boolean isSet(Class clazz, String name) {
        return StringUtils.hasText(getClassName(clazz, name));
    }

getClassName 具体实现如下:

1
2
3
4
5
6
7
8
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是啥呢

1
2
3
4
5
6
7
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");
    }

可以看到 其中有IRule.class对应 NFLoadBalancerRuleClassName

回头看getClassName类

1
String className = environment.getProperty(name + "." + NAMESPACE + "." + classNameProperty);

其中 name 为ribbon.client.name 也就是我们服务名,

NAMESPACE 为 ribbon

classNameProperty 为 NFLoadBalancerRuleClassName

所以通过getClassName 方法 最终返回的是 我们系统中设置的 serviceId.ribbon.NFLoadBalancerRuleClassName 属性值

接着看ribbonRule 第二行代码

1
<strong>return this</strong>.propertiesFactory.get(IRule.<strong>class</strong>, config, name);

具体get实现:

1
2
3
4
5
6
7
8
9
10
11
12
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;
    }</c></c>

这样就很清晰了,最终会根据我们配置的负载策略类全路径 生成对应的实例

而我们如果一个服务需要依赖调用N多服务的时候 采用这样的配置方式,显得有点繁琐,我们的负载配置不能全局化

怎么处理呢?

当然我们可以拓展org.springframework.cloud.netflix.ribbon.PropertiesFactory类 使其支持全局配置,但springcloud官方不推荐这样处理

结合我们目前项目的处理方式,这里我给出另一条思路

在配置文件中,我们添加一个属性

loadbalanced.services = service-A,service-B

另外添加一个RibbonLoadBalancerRuleConfiguration类

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
@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);
            }
        }
    }
 
}</string>

这样在配置文件中我们只需要配置

1
2
ribbon.NFLoadBalancerRuleClassName=自定义负载均衡策略
loadBalancedService=需要使用自定义负载均衡策略的服务

有时间会整理一篇更完整的ribbon负载均衡原理分析,敬请期待

cloud server ribbon 自定义策略配置的更多相关文章

  1. Spring Cloud Gateway Ribbon 自定义负载均衡

    在微服务开发中,使用Spring Cloud Gateway做为服务的网关,网关后面启动N个业务服务.但是有这样一个需求,同一个用户的操作,有时候需要保证顺序性,如果使用默认负载均衡策略,同一个用户的 ...

  2. Spring Cloud Netflix Ribbon详细介绍及自定义规则策略

    之前文章我们介绍了如何配置具有Ribbon轮询机制的负载均衡策略的消费者,这次来具体了解一下Ribbon的一些细节,以及如何自定义负载均衡策略等. 说一下Ribbon实现负载均衡的大致思路.它通过用@ ...

  3. 自定义Ribbon客户端策略

    说明   为了实现Ribbon细粒度的划分,让调用不同的微服务时采用不同的客户端负载均衡策略, 通常情况下我们会自定义配置策略.   本文以内容中心(content-center)调用户中心微服务(u ...

  4. 【SpringCloud】Ribbon如何自定义客户端配置和全局配置

    起因 事情的起因是这样的,公司内部要实现基于Zuul网关的灰度路由,在上线时进行灰度测试,故需要配置业务微服务向Eureka注册的metadata元数据,和自定义Ribbon的负载规则达到只访问灰度服 ...

  5. 笔记:Spring Cloud Feign Ribbon 配置

    由于 Spring Cloud Feign 的客户端负载均衡是通过 Spring Cloud Ribbon 实现的,所以我们可以直接通过配置 Ribbon 的客户端的方式来自定义各个服务客户端调用的参 ...

  6. Spring Cloud Feign Ribbon 配置

    由于 Spring Cloud Feign 的客户端负载均衡是通过 Spring Cloud Ribbon 实现的,所以我们可以直接通过配置 Ribbon 的客户端的方式来自定义各个服务客户端调用的参 ...

  7. 从零开始学spring cloud(六) -------- Ribbon

    一.Ribbon介绍 Ribbon就是客户端侧负责均衡实现的一种方式,那么Ribbon是什么呢? Ribbon是Netflix发布的云中间层服务开源项目,其主要功能是提供客户端侧负载均衡算法.Ribb ...

  8. SpringCloud的Ribbon自定义负载均衡算法

    1.Ribbon默认使用RoundRobinRule策略轮询选择server 策略名 策略声明 策略描述 实现说明 BestAvailableRule public class BestAvailab ...

  9. SpringCloud微服务实战——搭建企业级开发框架(三十六):使用Spring Cloud Stream实现可灵活配置消息中间件的功能

      在以往消息队列的使用中,我们通常使用集成消息中间件开源包来实现对应功能,而消息中间件的实现又有多种,比如目前比较主流的ActiveMQ.RocketMQ.RabbitMQ.Kafka,Stream ...

随机推荐

  1. iframe+form上传文件

    <iframe id="iframe1" name="ifra1" style="display: none"></ifr ...

  2. Linux主题:获取帮助

    Linux有多种方式获取帮助,这些帮助通过不同的命令,获得不同详细程度和文字量的帮助. help help方式有两种用法,一种是help command,另一种是command --help.前一种是 ...

  3. intellij idea 配置web 项目

    Intellij Idea 创建Web项目入门(一)(转载)   相关软件: Intellij Idea14:http://pan.baidu.com/s/1nu16VyD JDK7:http://p ...

  4. Mybatis高级应用-2

    文章内容简介 1.回顾 2.Mybatis配置文件解析 3.Mybatis映射文件解析 ResultMap标签使用 自定义返回值处理(Map) 关联映射 主键映射 一.回顾 Mybatis是ORM(o ...

  5. js版RSA算法

    // RSA, a suite of routines for performing RSA public-key computations in// JavaScript.//// Requires ...

  6. 30种提高mysql处理速度的方法

    1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 ...

  7. tensorflow pip install 安装指定版本的包并指定安装源(速度会快很多)

    pip install tensorflow-gpu==1.3 pip install tensorflow-gpu==1.4 # pip install 命令行pip install -i http ...

  8. 2.6、CDH 搭建Hadoop在安装(安装CDH和其他软件)

    第6步:安装CDH和其他软件 设置Cloudera Manager数据库后,启动Cloudera Manager Server,然后登录Cloudera Manager Admin Console: ...

  9. 一个查询指定错误记录数据表错误记录条数的shell脚本

    #!/bin/bash #author:skycheng #parameters db_user=dbuser db_pass=dbpass db_host=xxx.xxx.xxx.xxx datab ...

  10. selenium ide界面介绍

    Selenium Ide是firefox浏览器的一个插件,可以进行web的录制和回放,完成简单的自动化测试,同时可以将录制的脚本导出多种语言的脚本. 下面是Selenium Ide的界面: Base  ...