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


    1、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-cloud-starter-eureka已经依赖了spring-cloud-starter-ribbon,所以不用再添加spring-cloud-starter-ribbon依赖了   

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

    (2)配置ribbon参数

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

    (3)定义RestTemplate

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

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

    (5)测试代码

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

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

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

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

    (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);
        }
  • 相关阅读:
    IOS之Block的应用-textFeild的回调应用
    KVC与KVO的不同
    git
    perl读取excel
    Linux用户管理
    Linux软件包的管理
    linux系统学习(二)
    linux系统学习(一)
    js模版渲染
    Discuz核心函数的解析
  • 原文地址:https://www.cnblogs.com/dehigher/p/10134524.html
Copyright © 2020-2023  润新知