作者微信 bishe2022

代码功能演示视频在页面下方,请先观看;如需定制开发,联系页面右侧客服
深入理解Ribbon之源码解析

Custom Tab


RestTemplate和Ribbon相结合

Ribbon在Netflix组件是非常重要的一个组件,在Zuul中使用Ribbon做负载均衡,以及Feign组件的结合等。在Spring Cloud 中,作为开发中,做的最多的可能是将RestTemplate和Ribbon相结合,你可能会这样写:

@Configurationpublic class RibbonConfig {
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {        
    return new RestTemplate();
    }
}

消费另外一个的服务的接口,差不多是这样的:

@Servicepublic class RibbonService {
    @Autowired
    RestTemplate restTemplate;    
    public String hi(String name) {        
    return restTemplate.getForObject("http://eureka-client/hi?name="+name,String.class);
    }
}

深入理解Ribbon

LoadBalancerClient

在Riibon中一个非常重要的组件为LoadBalancerClient,它作为负载均衡的一个客户端。它在spring-cloud-commons包下:
的LoadBalancerClient是一个接口,它继承ServiceInstanceChooser,它的实现类是Ribb"http://wisdomdd.cn:8080/filestore/ueditor/jsp/upload/image/20180121/adca8b4857754e92ace9ff997f6ad0b6.png" alt="image.png" title=""/>

其中LoadBalancerClient接口,有如下三个方法,其中excute()为执行请求,reconstructURI()用来重构url:

public interface LoadBalancerClient extends ServiceInstanceChooser {
  <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
  <T> T execute(String serviceId, ServiceInstance serviceInstance, 
  LoadBalancerRequest<T> request) throws IOException;
  URI reconstructURI(ServiceInstance instance, URI original);

}

ServiceInstanceChooser接口,主要有一个方法,用来根据serviceId来获取ServiceInstance,代码如下:

public interface ServiceInstanceChooser {

    ServiceInstance choose(String serviceId);
}

LoadBalancerClient的实现类为Ribb"brush:java;toolbar:false">public class Ribb getServer(serviceId);                 if (server == null) {                     return null;         }                 return new RibbonServer(serviceId, server, isSecure(server, serviceId),                 serverIntrospector(serviceId).getMetadata(server));     }protected Server getServer(String serviceId) {             return getServer(getLoadBalancer(serviceId));    }protected Server getServer(ILoadBalancer loadBalancer) {            if (loadBalancer == null) {                return null;         }                 return loadBalancer.chooseServer("default");          // TODO: better handling of key     }protected ILoadBalancer getLoadBalancer(String serviceId) {             return this.clientFactory.getLoadBalancer(serviceId);     }     ...//省略代码

在Ribb"brush:java;toolbar:false">public interface ILoadBalancer {     public void addServers(List<Server> newServers);     public Server chooseServer(Object key);     public void markServerDown(Server server);     public List<Server> getReachableServers();     public List<Server> getAllServers(); }

其中,addServers()方法是添加一个Server集合;chooseServer()方法是根据key去获取Server;markServerDown()方法用来标记某个服务下线;getReachableServers()获取可用的Server集合;getAllServers()获取所有的Server集合。

DynamicServerListLoadBalancer

它的继承类为BaseLoadBalancer,它的实现类为DynamicServerListLoadBalancer,这三者之间的关系如下:

image.png

查看上述三个类的源码,可用发现,配置以下信息,IClientConfig、IRule、IPing、ServerList、ServerListFilter和ILoadBalancer,查看BaseLoadBalancer类,它默认的情况下,实现了以下配置:

Home