14 微服務電商【黑馬樂優商城】:day02-springcloud(理論篇四:配置Robbin負載均衡)

本項目的筆記和資料的Download,請點擊這一句話自行獲取。html

day01-springboot(理論篇) ;day01-springboot(實踐篇)算法

day02-springcloud(理論篇一)  ;day02-springcloud(理論篇二)  ;day02-springcloud(理論篇三:搭建Eureka註冊中心) ;day02-springcloud(理論篇四:配置Robbin負載均衡)spring

day03-springcloud(Hystix,Feign)  ;day03-springcloud(Zuul網關)springboot

14 微服務電商【黑馬樂優商城】:day02-springcloud


 

0.學習目標

  • 瞭解系統架構的演變
  • 瞭解RPC與Http的區別
  • 掌握HttpClient的簡單使用
  • 知道什麼是SpringCloud
  • 獨立搭建Eureka註冊中心
  • 獨立配置Robbin負載均衡

 

7.負載均衡Robbin

在剛纔的案例中,咱們啓動了一個user-service,而後經過DiscoveryClient來獲取服務實例信息,而後獲取ip和端口來訪問。架構

可是實際環境中,咱們每每會開啓不少個user-service的集羣。此時咱們獲取的服務列表中就會有多個,到底該訪問哪個呢?負載均衡

通常這種狀況下咱們就須要編寫負載均衡算法,在多個實例列表中進行選擇。框架

不過Eureka中已經幫咱們集成了負載均衡組件:Ribbon,簡單修改代碼便可使用。dom

什麼是Ribbon:微服務

接下來,咱們就來使用Ribbon實現負載均衡。學習

7.1.啓動兩個服務實例

首先咱們啓動兩個user-service實例,一個8081,一個8082。

Eureka監控面板: 

  

7.2.開啓負載均衡

由於Eureka中已經集成了Ribbon,因此咱們無需引入新的依賴。直接修改代碼:

在RestTemplate的配置方法上添加@LoadBalanced註解

@Bean
@LoadBalanced public RestTemplate restTemplate() {
    return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}

 修改調用方式,再也不手動獲取ip和端口,而是直接經過服務名稱調用: 

 

@Service
public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

public List<User> queryUserByIds(List<Long> ids) {
        List<User> users = new ArrayList<>();
        // 地址直接寫服務名稱便可
        String baseUrl = "http://user-service/user/";
        ids.forEach(id -> {
            // 咱們測試屢次查詢,
            users.add(this.restTemplate.getForObject(baseUrl + id, User.class));
            // 每次間隔500毫秒
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        return users;
    }
}

 訪問頁面,查看結果:

 

7.3.源碼跟蹤

爲何咱們只輸入了service名稱就能夠訪問了呢?以前還要獲取ip和端口。

顯然有人幫咱們根據service名稱,獲取到了服務實例的ip和端口。它就是LoadBalancerInterceptor

咱們進行源碼跟蹤:

 

 繼續跟入execute方法:發現獲取了8082端口的服務

 

 再跟下一次,發現獲取的是8081:

 


 

7.4.負載均衡策略

Ribbon默認的負載均衡策略是簡單的輪詢,咱們能夠測試一下:

編寫測試類,在剛纔的源碼中咱們看到攔截中是使用RibbonLoadBalanceClient來進行負載均衡的,其中有一個choose方法,是這樣介紹的:

 

如今這個就是負載均衡獲取實例的方法。

咱們對注入這個類的對象,而後對其測試:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = UserConsumerDemoApplication.class)
public class LoadBalanceTest {

    @Autowired
    RibbonLoadBalancerClient client;

    @Test
    public void test(){
        for (int i = 0; i < 100; i++) {
            ServiceInstance instance = this.client.choose("user-service");
            System.out.println(instance.getHost() + ":" + instance.getPort());
        }
    }
}

 結果:

 

符合了咱們的預期推測,確實是輪詢方式。

咱們是否能夠修改負載均衡的策略呢?

繼續跟蹤源碼,發現這麼一段代碼:

 

 咱們看看這個rule是誰:

 

 這裏的rule默認值是一個RoundRobinRule,看類的介紹: 

 

這不就是輪詢的意思嘛。

咱們注意到,這個類實際上是實現了接口IRule的,查看一下:

 

定義負載均衡的規則接口。

它有如下實現:

 

 SpringBoot也幫咱們提供了修改負載均衡規則的配置入口:

 

user-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

 

格式是:{服務名稱}.ribbon.NFLoadBalancerRuleClassName,值就是IRule的實現類。
再次測試,發現結果變成了隨機:

7.5.重試機制

Eureka的服務治理強調了CAP原則中的AP,便可用性和可靠性。它與Zookeeper這一類強調CP(一致性,可靠性)的服務治理框架最大的區別在於:Eureka爲了實現更高的服務可用性,犧牲了必定的一致性,極端狀況下它寧願接收故障實例也不肯丟掉健康實例,正如咱們上面所說的自我保護機制。

可是,此時若是咱們調用了這些不正常的服務,調用就會失敗,從而致使其它服務不能正常工做!這顯然不是咱們願意看到的。

咱們如今關閉一個user-service實例:

 

 由於服務剔除的延遲,consumer並不會當即獲得最新的服務列表,此時再次訪問你會獲得錯誤提示:

可是此時,8081服務實際上是正常的。

所以Spring Cloud 整合了Spring Retry 來加強RestTemplate的重試能力,當一次服務調用失敗後,不會當即拋出一次異常,而是再次重試另外一個服務。

只須要簡單配置便可實現Ribbon的重試:

spring:
  cloud:
    loadbalancer:
      retry:
        enabled: true # 開啓Spring Cloud的重試功能
user-service:
  ribbon:
    ConnectTimeout: 250 # Ribbon的鏈接超時時間
    ReadTimeout: 1000 # Ribbon的數據讀取超時時間
    OkToRetryOnAllOperations: true # 是否對全部操做都進行重試
    MaxAutoRetriesNextServer: 1 # 切換實例的重試次數
    MaxAutoRetries: 1 # 對當前實例的重試次數

 

根據如上配置,當訪問到某個服務超時後,它會再次嘗試訪問下一個服務實例,若是不行就再換一個實例,若是不行,則返回失敗。切換次數取決於MaxAutoRetriesNextServer參數的值。

引入spring-retry依賴

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

 咱們重啓user-consumer-demo,測試,發現即便user-service2宕機,也能經過另外一臺服務實例獲取到結果!

 

 

=============================================

參考資料:

Spring Cloud升級最新Finchley版本的全部坑

 

end

相關文章
相關標籤/搜索