zoukankan      html  css  js  c++  java
  • RestTemplate 负载均衡原理

    RestTemplate 是通过拦截器改变请求的URI的方式来指定服务器的,此处将通过一个自定义LoadBalanced的方式来进行说明

    1.导入jar包

    <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>2.0.2.RELEASE</version>
      </parent>
    
      <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
      </dependencies>

    2.自定义 MyLoadBalanced 注解

    import org.springframework.beans.factory.annotation.Qualifier;
    
    import java.lang.annotation.*;
    
    @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Qualifier
    public @interface MyLoadBalanced {
    }

    3.编写配置类

    import org.springframework.beans.factory.SmartInitializingSingleton;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.client.ClientHttpRequestInterceptor;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.Collections;
    import java.util.List;
    
    @Configuration
    public class MyConfig {
    
        @Autowired(required = false)
        @MyLoadBalanced
        private List<RestTemplate> tpls = Collections.emptyList();
    
        @Bean
        public SmartInitializingSingleton lbInitializing() {
            return new SmartInitializingSingleton() {
                @Override
                public void afterSingletonsInstantiated() {
                    System.out.println("tpls 的数量:"+tpls.size());
                    for (RestTemplate tpl : tpls) {
                        List<ClientHttpRequestInterceptor> interceptors = tpl.getInterceptors();
                        interceptors.add(new MyInterceptor());
                        tpl.setInterceptors(interceptors);
                    }
    
                }
            };
        }
    }

    4.编写Controller测试接口 (访问 /getUser 可以发现执行的是自定义的 MyLoadBalanced  此处应该会报错,因为地址不存在,不过我们主要是为了测试是否会执行 MyLoadBalanced)

    import com.idelan.ribbon.config.MyLoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    @RestController
    @Configuration
    public class MyController {
    
        @Bean
        @MyLoadBalanced
        public RestTemplate tplA() {
            return new RestTemplate();
        }
    
        @GetMapping(value = "/getUser")
        public String getUser() {
            RestTemplate restTemplate = tplA();
           String json = restTemplate.getForObject("http://smart-platform-base/platform/base/getUser", String.class);
            return json;
        }
    
        @GetMapping(value = "/hello")
        public String hello() {
            return "hello world";
        }
    }

    5.自定义拦截器来更改接口的访问地址 (@LoadBalanced 此处的逻辑会别我们复杂很多,我们只是简单模拟一下)

    (1)自定义 Request 类

    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.HttpRequest;
    
    import java.net.URI;
    import java.net.URISyntaxException;
    
    public class MyRequest implements HttpRequest {
    
        HttpRequest httpRequest;
    
        public MyRequest(HttpRequest httpRequest) {
            this.httpRequest = httpRequest;
        }
    
        @Override
        public HttpMethod getMethod() {
            return httpRequest.getMethod();
        }
    
        @Override
        public String getMethodValue() {
            return httpRequest.getMethodValue();
        }
    
        @Override
        public URI getURI() {
            try {
                URI newUri = new URI("http://localhost:8080/hello");
                return newUri;
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
            return httpRequest.getURI();
        }
    
        @Override
        public HttpHeaders getHeaders() {
            return httpRequest.getHeaders();
        }
    }

    (2)自定义拦截器

    import org.springframework.http.HttpRequest;
    import org.springframework.http.client.ClientHttpRequestExecution;
    import org.springframework.http.client.ClientHttpRequestInterceptor;
    import org.springframework.http.client.ClientHttpResponse;
    
    import java.io.IOException;
    
    public class MyInterceptor implements ClientHttpRequestInterceptor {
    
        @Override
        public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
            System.out.println("~~~~~~~~自定义拦截器,uri:"+httpRequest.getURI());
            System.out.println("旧的uri:"+httpRequest.getURI());
    
            HttpRequest newRequest = new MyRequest(httpRequest);
            System.out.println("新的uri:"+newRequest.getURI());
            return clientHttpRequestExecution.execute(newRequest, bytes);
        }
    }

    测试:可以通过访问 /getUser 接口来测试,最终会返回 /hello 接口的内容,因为我们更改了访问地址

  • 相关阅读:
    [bzoj1263]整数划分
    [bzoj3171]循环格
    [bzoj3551]Peaks加强版
    [bzoj3307]雨天的尾巴
    [bzoj2756]奇怪的游戏
    [bzoj4025]二分图
    人比人该死啊
    数据挖掘十大经典算法[0]-K-Means算法
    ISODATA算法
    CodeForces Round 197 Div2
  • 原文地址:https://www.cnblogs.com/gyli20170901/p/10075884.html
Copyright © 2011-2022 走看看