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 接口的內容,因為我們更改了訪問地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM