虽然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. windows下面的java项目打成jar放到XShell终端上面进行远程调试

    前言: java项目打成jar放到linux上面运行,但是linux上面没有eclipse不能进行debug,所以要在windows的eclipse中进行远程调试. 需要注意的是!!!-->在e ...

  2. TensorFlow实战——个性化推荐

    原创文章,转载请注明出处: http://blog.csdn.net/chengcheng1394/article/details/78820529 请安装TensorFlow1.0,Python3. ...

  3. openresty(完整版)Lua拦截请求与响应信息日志收集及基于cjson和redis动态路径以及Prometheus监控(转)

    直接上文件 nginx.conf #运行用户和组,缺省为nobody,若改为别的用户和组,则需要先创建用户和组 #user wls81 wls; #开启进程数,一般与CPU核数等同 worker_pr ...

  4. 3.有关于Python列表简述

    一..title() [让所选择的列表元素的第一个字母大写] test = ['no1','No2','No3','No4'] book = "This My " + test[0 ...

  5. Oracle VM VirtualBox各种显示模式切换 热键

    初用VirtualBox, 几个显示切换快捷键还是要记一下的: Right Ctrl + F        -- 切换到全屏模式 Right Ctrl + L        -- 切换到无缝模式 Ri ...

  6. oracle归档日志关闭和打开

    查询归档日志状态 方法一 SQL> archive log list; 方法二 SQL> select name,log_mode from V$database; 打开归档日志 orac ...

  7. angularjs 与 UEditor开发,添加directive,保证加载顺序正常

    'use strict'; angular.module('app.core').directive('ueditor', [function () { return { restrict: 'A', ...

  8. scala private

    class Person private(val name:String) private 修饰整个类的参数,其实效果类似于java的私有化构造方法,无法通过new Person(..) 来实例化对象 ...

  9. Structs复习 通配符

    1.jar包 web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version= ...

  10. oracle理解和导入导出

    搞过sql server的程序员很难理解oracle的表空间.我在这里简单说一下吧, oracle中的表空间就相当于sql server中的实例,用户就相当于sql server中的库. 所以在ora ...