1. 程式人生 > >從零開始學spring cloud(六) -------- Ribbon

從零開始學spring cloud(六) -------- Ribbon

lec nbsp cor rest cati 1.0 pac 超時 註冊

一、Ribbon介紹

技術分享圖片

技術分享圖片

Ribbon就是客戶端側負責均衡實現的一種方式,那麽Ribbon是什麽呢?

Ribbon是Netflix發布的雲中間層服務開源項目,其主要功能是提供客戶端側負載均衡算法。Ribbon客戶端組件提供一系列完善的配置項如連接超時,重試等。簡單的說,Ribbon是一個客戶端負載均衡器,我們可以在配置文件中列出Load Balancer後面所有的機器,Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機連接等)去連接這些機器,我們也很容易使用Ribbon實現自定義的負載均衡算法。

下圖展示了Eureka使用Ribbon時候的大致架構:

技術分享圖片


Ribbon工作時分為兩步:第一步先選擇 Eureka Server, 它優先選擇在同一個Zone且負載較少的Server;第二步再根據用戶指定的策略,在從Server取到的服務註冊列表中選擇一個地址。其中Ribbon提供了多種策略,例如輪詢round robin、隨機Random、根據響應時間加權等。

二、Ribbon示例

查看官方接口文檔:https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.1.0.RELEASE/single/spring-cloud-netflix.html#netflix-ribbon-starter

To include Ribbon in your project, use the starter with a group ID of org.springframework.cloud and an artifact ID of spring-cloud-starter-netflix-ribbon

. See the Spring Cloud Project page for details on setting up your build system with the current Spring Cloud Release Train.

我們現在MOVIE的微服務中,添加相應的依賴

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

然後,我們只需要在啟動類的中有個bean上面,增加一個@LoadBalanced,就可以實現客戶端側的負載均衡

 1 package com.zwjk.cloud;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 6 import org.springframework.context.annotation.Bean;
 7 import org.springframework.web.client.RestTemplate;
 8 
 9 @SpringBootApplication
10 public class MovieRibbonApplication {
11 
12     @Bean
13     @LoadBalanced
14     public RestTemplate restTemplate() {
15         return new RestTemplate();
16     }
17 
18     public static void main(String[] args) {
19         SpringApplication.run(MovieRibbonApplication.class, args);
20     }
21 
22 }

下面。我們啟動兩個user服務,端口分別是7901,7902,然後通過movie服務進行訪問,通過查看兩個的user的日誌,展示請求的分發。這裏我們需要修改一下配置文件,將原先的

userServicePath: http://localhost:7900/simple/

修改成:

userServicePath: http://microservice-provider-user/simple/

這是通過一個虛擬的host進行訪問,這樣,就能隨機的訪問兩個user服務了

啟動後,查看一下Eureka的控制臺,可以看到一個服務的兩個實例運行著

技術分享圖片

請求了4次後,發現,7901和7900各自獲得兩次請求。這是因為Ribbon默認的負載均衡的策略是輪詢。

下面,我們看一下,如何來定制Ribbon的負載均衡策略,

You can configure some bits of a Ribbon client by using external properties in <client>.ribbon.*, which is similar to using the Netflix APIs natively, except that you can use Spring Boot configuration files. The native options can be inspected as static fields in CommonClientConfigKey (part of ribbon-core).

Spring Cloud also lets you take full control of the client by declaring additional configuration (on top of the RibbonClientConfiguration) using @RibbonClient, as shown in the following example:

您可以使用<client> .ribbon。*中的外部屬性配置Ribbon客戶端的某些位,這類似於本機使用Netflix API,但您可以使用Spring Boot配置文件。 可以在CommonClientConfigKey(ribbon-core的一部分)中將本機選項作為靜態字段進行檢查。

Spring Cloud還允許您通過使用@RibbonClient聲明其他配置(在RibbonClientConfiguration之上)來完全控制客戶端,如以下示例所示:

技術分享圖片

需要註意的是,這個有一個警告,說,@Confiuration 不能放在@ComponentScan和SpringBootApplication掃描的路徑下,那就把這個配置文件,放在掃描的包的外面。

官方文檔說,我們可以自定義配置,來實現自己的負載均衡的策略,我們在代碼中來實現一下;

技術分享圖片

通過在外部,增加一個自定義的配置文件,要實現自定義的規則,規則設置為隨機,啟動Movie,並進行訪問,查看user響應是否隨機,

通過測試,可以發現,請求是隨機的。

假設,我有多個ribbonClient,那麽該怎麽實現呢?(上述的方式,其實已經實現了這種方式,下面看一下多個ribbon的實現示例)

現在,我們在啟動兩個user,用兩個新的服務名稱

技術分享圖片

現在修改movie,使用兩個不同的策略,訪問兩個不同的服務,

 1 package com.zwjk.cloud.controller;
 2 
 3 import com.zwjk.cloud.entity.User;
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.beans.factory.annotation.Value;
 6 import org.springframework.cloud.client.ServiceInstance;
 7 import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
 8 import org.springframework.web.bind.annotation.GetMapping;
 9 import org.springframework.web.bind.annotation.PathVariable;
10 import org.springframework.web.bind.annotation.RestController;
11 import org.springframework.web.client.RestTemplate;
12 
13 /**
14  * @author : Jixiaohu
15  * @Date : 2019-04-11.
16  * @Time : 9:38.
17  * @Description :
18  */
19 @RestController
20 public class MovieController {
21 
22     @Autowired
23     private RestTemplate restTemplate;
24 
25     @Value("${user.userServicePath}")
26     private String userServicePath;
27 
28     @Autowired
29     private LoadBalancerClient loadBalancerClient;
30 
31     @GetMapping("/movie/{id}")
32     public User findById(@PathVariable Long id) {
33         return this.restTemplate.getForObject(this.userServicePath + id, User.class);
34     }
35 
36     @GetMapping("/test")
37     public String test() {
38         ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");
39         System.out.println("111" + ":" + serviceInstance.getServiceId() + ":" + serviceInstance.getHost() + ":" + serviceInstance.getPort());
40 
41         ServiceInstance serviceInstance2 = this.loadBalancerClient.choose("microservice-provider-user2");
42         System.out.println("222" + ":" + serviceInstance2.getServiceId() + ":" + serviceInstance2.getHost() + ":" + serviceInstance2.getPort());
43 
44         return "1";
45     }
46 
47 }

啟動項目,然後訪問,並查看控制臺日誌:

技術分享圖片

可以看出來,訪問user服務是隨機的,訪問user2服務,是輪詢的。

下面我們看一下,當我們把配置文件放在掃描包下的情況:

技術分享圖片

技術分享圖片

查看結果,發現,隨機的策略對兩個服務都產生了影響

假設,就是想要放在這裏呢?當然可以,可以通過編寫註解,在掃描包的時候,排除配置文件

我們編寫一個空的註解

 1 package com.zwjk.cloud.exclude;
 2 
 3 /**
 4  * @author : Jixiaohu
 5  * @Date : 2019-04-11.
 6  * @Time : 20:11.
 7  * @Description :
 8  */
 9 public @interface ExcludeFromComponentScan {
10 }

同時在Configuration類上增加該註解 @ExcludeFromComponentScan ,最後,在啟動類上,使用@ComponentScan 註解掃描時,排除被@ExcludeFromComponentScan修飾的類

看一下啟動類的註解:

 1 package com.itmuch.cloud;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 6 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 7 import org.springframework.cloud.netflix.ribbon.RibbonClient;
 8 import org.springframework.context.annotation.Bean;
 9 import org.springframework.context.annotation.ComponentScan;
10 import org.springframework.context.annotation.FilterType;
11 import org.springframework.web.client.RestTemplate;
12 
13 @SpringBootApplication
14 @EnableEurekaClient
15 @RibbonClient(name = "microservice-provider-user", configuration = TestConfiguration.class)
16 @ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, value = ExcludeFromComponentScan.class) })
17 public class ConsumerMovieRibbonApplication {
18 
19   @Bean
20   @LoadBalanced
21   public RestTemplate restTemplate() {
22     return new RestTemplate();
23   }
24 
25   public static void main(String[] args) {
26     SpringApplication.run(ConsumerMovieRibbonApplication.class, args);
27   }
28 }

我們同樣來啟動一下代碼,並測試一下效果:

技術分享圖片

user遵循的random的機制,user2遵循著round robin機制

負載均衡的機制,同樣可以通過配置文件進行修改,通過配置文件配置的,優先級是最高的。

下面將通過配置文件,來修改負責均衡機制

技術分享圖片

在配置文件中,增加<服務名>.ribbon.NFLoadBalancerRuleClassName,

spring:
  application:
    name: microservice-consumer-movie-ribbon-properties
server:
  port: 8010
eureka:
  client:
    healthcheck:
      enabled: true
    serviceUrl:
      defaultZone: http://user:[email protected]:8761/eureka
  instance:
    prefer-ip-address: true
microservice-provider-user:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

技術分享圖片

查看結果,microservice-provider-user遵循著隨機的原則,microservice-provider-user2 遵循著默認的輪詢機制

從零開始學spring cloud(六) -------- Ribbon