链接: github  https://github.com/Netflix/ribbon/wiki

            知乎  https://zhuanlan.zhihu.com/p/28547575

            spring社区 http://projects.spring.io/spring-cloud/spring-cloud.html#_spring_cloud_netflix


对HTTP和TCP客户端进行负载均衡控制

ribbon是客户端负载均衡,Feign默认使用了ribbon技术

同时zuul也使用ribbon做负载均衡


Ribbon的源码实现大致原理:

LoadBalancerClient : 继承了ServiceInstanceChooser接口,实现类是RibbonLoadBalancerClient.主要方法有choose(ServiceInstanceChooser用来选择instance) ,

                                     execute(LoadBalancerClient 用来执行).

ILoadBalancer   : 接口方法有addServers,chooseServer,markServerDown,getReachableServers,getAllServers. 用途同方法名

                                实现类为BaseLoadBalancer 和 DynamicServerListLoadBalancer.

BaseLoadBalancer : 主要由以下类进行配置 IClientConfig(基本配置,用于初始化)  IRule(路由策略)  IPing (判断响应)  (静态配置负载均衡)

DynamicServerListLoadBalancer: ServerList(用于从Eureka中获取服务列表)  ServerListFilter(列表过滤)                          (动态配置负载均衡)


负载均衡过程:

 1.RibbonLoadBalancerClient接收到一个serviceid之后,调用ServiceInstanceChooser的choose方法,choose方法首先得到 ILoadBalancer (当中有client列表)。

    再利用ILoadBalancer 的chooseServer方法得到普通Server实例并实例化RibbonServer,并返回。chooseserver会通过loadbalancer中的rule来返回正确的instance。

2. DynamicServerListLoadBalancer由iconfig初始化,初始化完成后调用updateListOfServers方法获得所有ServerList。(方法中通过ServerList实现类来访问EurekaClient中的注册列表)

3.BaseLoadBalancer中有一个PingTask任务,他每10秒钟会向EurekaClient发送一个Ping。如果从Eureka拉取的注册列表发生了改变,则重新更新列表。

4.LoadBalancerClient根据注册列表和IRule来进行负载均衡


@LoadBalanced注解的原理

被注解后,会维护一个restTemplate的列表。表中所有template都会被添加拦截器,拦截器会调用LoadBalancerClient接口的execute方法




springcloud中的应用

springcloud提供了默认的配置RibbonClientConfiguration。它提供了包含ILoadBalancer,ServerListFilter在内的许多配置。

你可以更改默认的配置,更改方法为在.property文件中添加<client>.ribbon.*的配置项

使用重写的配置java类,如:

@Configuration
@RibbonClient(name = "foo", configuration = FooConfiguration.class)
public class TestConfiguration {
}
这个client会同时使用默认的RibbonClientConfiguration和FooConfiguration配置,重复项后者会覆盖前者。重写的配置类最好放在一个其他的package中再引入,这样就不会被@ComponentScan自动扫描,被所有的@RibbonClient使用。

重写配置类:

@Configuration
public class FooConfiguration {
    @Bean
    public IPing ribbonPing(IClientConfig config) {
        return new PingUrl();
    }
}

同时使用Eureka和Ribbon,Eureka会将Ribbon中的众多接口重新实现以达到目的

如果没有使用Eureka,则需要添加配置项以激活RibbonClient的name属性,在application.yml中添加

stores:
  ribbon:
    listOfServers: example.com, google.com

直接使用Ribbon的Api

public class MyClass {
    @Autowired
    private LoadBalancerClient loadBalancer;

    public void doStuff() {
        ServiceInstance instance = loadBalancer.choose("stores");
        URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
        // ... do something with the URI
    }
}
LoadBalancerClient会根据clientid得到正确的instance的URI,过程如开篇所讲


使用@RibbonClient和@LoadBalanced注解的实例  https://spring.io/guides/gs/client-side-load-balancing/



Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐