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

 


免責聲明!

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



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