天天看點

SpringCloud入門(三):服務消費者RestTemplate+Ribbon(Greenwich.SR2)

以上一篇【SpringCloud入門(二):Restful API-RestTemplate(Greenwich.SR2)】為基礎來繼續。

我們知道RestTemplate是負責服務與服務之間的通訊的,但在微服務中,一般上服務都不會進行單點部署的,都會至少部署2台及以上的。現在我們有了注冊中心進行服務清單的維護,就需要一個用戶端負載均衡來進行動态服務的調用。

何為負載均衡

負載均衡(Load Balance)是分布式系統架構設計中必須考慮的因素之一,它通常是指,将請求/資料【均勻】分攤到多個操作單元上執行,負載均衡的關鍵在于【均勻】。

Ribbon

Spring Cloud Ribbon是一個基于Http和TCP的客服端負載均衡工具,它是基于Netflix Ribbon實作的。與Eureka配合使用時,Ribbon 可自動從Eureka Server (注冊中心) 擷取服務提供者位址清單,并基于負載均衡算法,通過在用戶端中配置ribbonServerList來設定服務端清單去輪詢通路以達到均衡負載的作用。

服務提供者

在microservice-provider子產品中,新增getRibbonBalancer接口。啟動8764和8765兩個端口。

idea多端口方式之一,-Dserver.port=8765

SpringCloud入門(三):服務消費者RestTemplate+Ribbon(Greenwich.SR2)
/**
     * @describe Ribbon負載均衡測試
     * @author: hero良
     * @param
     * @return:
     */
    @GetMapping("/getRibbonBalancer")
    public String getRibbonBalancer(String name){
        log.debug("************接受到請求*************");
        return "hello !" + name+" , this is 8764";
    }

           

兩個執行個體都已經注冊到注冊中心

SpringCloud入門(三):服務消費者RestTemplate+Ribbon(Greenwich.SR2)

服務消費者,分兩種情況

  • 項目使用了eureka
  • 項目未使用eureka
1.使用eureka

pom依賴

<!--使用了eureka-->
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
 </dependency>
           

yml

spring:
  application:
    name: ribbon

server:
  port: 8766

eureka:
  client:
    service-url:
      #單機版
      defaultZone: http://eureka1:8761/eureka/
      #叢集模式
    #      defaultZone: http://eureka1:8761/eureka/,http://eureka2:8762/eureka/,http://eureka3:8763/eureka/
           
2.未使用eureka

需要引入ribbon依賴

<!--項目未使用eureka-->
<!--<dependency>-->
     <!--<groupId>org.springframework.cloud</groupId>-->
     <!--<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>-->
 <!--</dependency>-->
           

yml

provider-service:
  ribbon:
#    未使用eureka或者禁用從注冊中心擷取服務提供者資訊時,需要自己維護位址  請求的服務位址,ip:port,多個時使用 逗号 隔開
    listOfServers: 127.0.0.1:8764,127.0.0.1:8765
           

在RestTemplate配置Bean新增 @LoadBalanced

@Bean
@LoadBalanced //開啟負載均衡注解
 public RestTemplate restTemplate(){
     return new RestTemplate();
 }
           

這裡直接使用服務名調用

public String getRibbonBalancer(String name){
        return restTemplate.getForObject("http://provider-service/appController/getRibbonBalancer?name="+name, String.class);
    }
           
/**
     * @description ribbon的負載均衡
     * @author hero良
     * @param name
     * @return java.lang.String
     * @exception
     * @version  1.0
     */
    @GetMapping("/getRibbonBalancer")
    public String getRibbonBalancer(String name){
        return ribbonService.getRibbonBalancer(name);
    }
           

使用postman來測試接口8764和8765交替出現,因為Ribbon的負載政策預設是輪詢

SpringCloud入門(三):服務消費者RestTemplate+Ribbon(Greenwich.SR2)
SpringCloud入門(三):服務消費者RestTemplate+Ribbon(Greenwich.SR2)

在yml中類修改負載政策,也可以使用Bean的方式來配置。

provider-service:
  ribbon:
    #負載均衡政策
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置規則 随機
    #  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置規則 輪詢
    #  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置規則 重試
    #  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置規則 響應時間權重
    #  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule #配置規則 最空閑連接配接政策
           

provider-service 表示局部配置,隻針對這個服務有效,也可以使用全局配置,如下

ribbon:
    #負載均衡政策
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置規則 随機
           

Ribbon的逾時、重試

RestTemplate結合Ribbon時,逾時需要配置RestTemplate的逾時,配置Ribbon時無效。

@Bean
@LoadBalanced //開啟負載均衡注解
public RestTemplate restTemplate(){
   HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
   httpRequestFactory.setConnectTimeout(500);
   httpRequestFactory.setReadTimeout(2000);
   return new RestTemplate(httpRequestFactory);
}

//無效
serviceId:
	ribbon:
		ReadTimeout: 1000
		ConnectTimeout: 1000
           

Ribbon通過增加Spring-retry還有相關配置開啟了重試,這個重試機制對于OpenFeign是不起作用的,但是對于 @LoadBalanced注解修飾的RestTemplate是有作用的。

<!-- https://mvnrepository.com/artifact/org.springframework.retry/spring-retry -->
        <!--重試需要此依賴-->
        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
            <version>1.2.4.RELEASE</version>
        </dependency>
           

yml配置

provider-service:
  ribbon:
    #負載均衡政策
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置規則 随機
    #  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置規則 輪詢
    #  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置規則 重試
    #  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置規則 響應時間權重
    #  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule #配置規則 最空閑連接配接政策
    # 同一執行個體最大重試次數,不包括首次調用
    MaxAutoRetries: 1
    # 重試其他執行個體的最大重試次數,不包括首次所選的server
    MaxAutoRetriesNextServer: 2
    # 是否所有操作都進行重試
    #當OkToRetryOnAllOperations設定為false時,隻會對get請求進行重試。
    #如果設定為true,便會對所有的請求進行重試,如果是put或post等寫操作,
    #如果伺服器接口沒做幂等性,會産生不好的結果,是以OkToRetryOnAllOperations慎用。
    OkToRetryOnAllOperations: false
           

新增getRibbonTimeout接口

/**
     * @description ribbon的逾時與重試
     * 逾時需要在建立RestTemplate的時候指定時間,配置在配置檔案中不生效,重試需要引入Spring-retry依賴
     * @author hero良
     * @return java.lang.String
     * @exception
     * @version  1.0
     */
    @GetMapping("/getRibbonTimeout")
    public String getRibbonTimeout(){
        return restTemplate.getForObject("http://provider-service/appController/getRibbonTimeout", String.class);
    }
           

服務提供者

這裡使用了sleep,讓線程阻塞,達到逾時重試的效果,sleep的時間要比設定的逾時時間大,不然等于沒設定。

/**
     * @describe Ribbon逾時測試
     * @author: hero良
     * @param
     * @return: 
     */
    @GetMapping("/getRibbonTimeout")
    public String getRibbonTimeout(){
        log.debug("************接受到請求*************");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello";
    }
           

調用後我們可以看到服務端的日志輸出

SpringCloud入門(三):服務消費者RestTemplate+Ribbon(Greenwich.SR2)
SpringCloud入門(三):服務消費者RestTemplate+Ribbon(Greenwich.SR2)

兩個服務加起來一共是6次請求,既實作了負載均衡也實作了 逾時重試

重試計算公式

MaxAutoRetries+MaxAutoRetriesNextServer+(MaxAutoRetries * MaxAutoRetriesNextServer) ,即重試5次 (不包括首次調用)一共産生6次調用。

繼續閱讀