Ribbon使用及其客户端负载均衡实现原理分析

一、ribbon负载均衡测试

(1)consumer工程添加依赖算法

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
        </dependency>

 

 说明:spring

①因为spring-cloud-starter-eureka已经依赖了spring-cloud-starter-ribbon,因此不用再添加spring-cloud-starter-ribbon依赖了   服务器

②Spring cloud 引入ribbon 配合restTemplate 实现客户端负载均衡、此处须要引入Okhttp依赖 (也能够使用ApacheClient等其余远程调用技术)负载均衡

 

(2)配置ribbon参数ide

#配置ribbon
ribbon: 
  MaxAutoRetries: 2 #最大重试次数,当Eureka中能够找到服务,可是链接不上时将会重试
  MaxAutoRetriesNextServer: 3 #切换实例的重试次数、高可用场景
  OkToRetryOnAllOperation: false #对全部操做请求都进行重试,若是是get则能够,若是是post、put有重复提交的危险,建议设置为false
  ConnectTimeout: 5000 #请求链接的超时时间
  ReadTimeout: 6000 #请求处理的超时时间    

 

 

(3)定义RestTemplatepost

    @Bean
    @LoadBalanced //使用该注解表示实现客户端负载均衡
    public RestTemplate restTemplate(){
        return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
    }

 

 

 

(4)启动两各Producer工程,注意端口不一样,注册到Eureka中测试

 

(5)测试代码this

@SpringBootTest
@RunWith(SpringRunner.class)
public class TestRibbon {
    
    @Autowired
    private RestTemplate restTemplate;

    @Test
    public void testRibbon(){
        
        String serviceId = "Producer";
        for(int i=0;i<10;i++){
            //经过服务id调用
            ResponseEntity<User> user= restTemplate.getForEntity("http://"+serviceId+"/user/get/5a754adf6abb500ad05688d9", User.class);
            System.out.println(JSONObject.toJSONString(user));
        }
    }
}

 

 

 

二、客户端负载均衡实现原理

(1)区别服务端负载均衡和客户端负载均衡spa

向Nginx 、F5 等在请求发出以后,被负载均衡服务器拦截再分发到具体服务的方式是服务端负载均衡,而Ribbon是客户端先从Eureka Server获取服务列表,本身维护服务列表,根据负载均衡算法直接请求资源服务器的方式叫服务端负载均衡rest

(2)Ribbon 实现客户端负载均衡细节

在定义RestTempalte时加@LoadBalanced注解后、restTemplate会走LoadbanlanceInterceptor拦截器 

LoadbanlanceInterceptor.class

@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
final ClientHttpRequestExecution execution) throws IOException {
  final URI originalUri = request.getURI();
      String serviceName = originalUri.getHost();
      Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
      //调用RibbonLoadBalancerClient
      return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
}
 


RibbonLoadBalancerClient.class
@Override
    public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
        //获取服务列表
        ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
        //根据负载均衡算法从服务列表中获取本次调用服务的地址
        Server server = getServer(loadBalancer);
        if (server == null) {
            throw new IllegalStateException("No instances available for " + serviceId);
        }
        RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,
                serviceId), serverIntrospector(serviceId).getMetadata(server));
        return execute(serviceId, ribbonServer, request);
    }
相关文章
相关标签/搜索