【夯實Spring Cloud】Spring Cloud中使用Ribbon實現負載均衡詳解(下)

本文屬於【夯實Spring Cloud】系列文章,該系列旨在用通俗易懂的語言,帶大家瞭解和學習Spring Cloud技術,希望能給讀者帶來一些乾貨。系列目錄如下:

【夯實Spring Cloud】Dubbo沉睡5年,Spring Cloud開始崛起!
【夯實Spring Cloud】Spring Cloud中基於maven的分佈式項目框架的搭建
【夯實Spring Cloud】Spring Cloud中的Eureka服務註冊與發現詳解
【夯實Spring Cloud】Spring Cloud中如何完善Eureka中的服務信息
【夯實Spring Cloud】Spring Cloud中使用Eureka集羣搭建高可用服務註冊中心
【夯實Spring Cloud】Spring Cloud中的Eureka和Zookeeper的區別在哪?
【夯實Spring Cloud】Spring Cloud中使用Ribbon實現負載均衡詳解(上)
【夯實Spring Cloud】Spring Cloud中使用Ribbon實現負載均衡詳解(下)
【夯實Spring Cloud】Spring Cloud中自定義Ribbon負載均衡策略(正在寫……)
【夯實Spring Cloud】Spring Cloud中使用Feign實現負載均衡詳解(正在寫……)
【夯實Srping Cloud】Spring Cloud中使用Hystrix實現斷路器原理詳解(正在寫……)
【夯實Spring Cloud】Spring Cloud中使用Zuul實現路由網關詳解(正在寫……)
【夯實Spring Cloud】Spring Cloud分佈式配置中心詳解(正在寫……)
【夯實Spring Cloud】未完待續


在上一篇文章中,我對 Ribbon 做了一個介紹,Ribbon 可以實現直接通過服務名稱對服務進行訪問。這一篇文章我詳細分析一下如何使用 Ribbon 實現客戶端的負載均衡。

1. 使用 Ribbon 實現負載均衡

要實現負載均衡,首先要有多個訂單服務提供者,目前我們就一個 microservice-order-provider01,端口號 8001,我們可以仿照這個服務,再創建兩個子模塊,也是訂單服務提供者,取名爲 microservice-order-provider02,端口號 8002 和 microservice-order-provider03,端口號 8003。

我們來看一下,使用 Ribbon 之後的架構圖。

Ribbon負載均衡

Ribbon 是客戶端的負載均衡工具,它在服務的消費方,首先三個訂單服務 8001、8002和8003都會註冊到 Eureka 集羣,Ribbon 會先從 Eureka 集羣中查詢可用的服務列表,然後根據 Ribbon 提供的負載均衡算法,負載均衡的請求可用的訂單服務。

Ribbon 默認的負載均衡算法是輪詢,也就是按順序挨個的調用。我們先來搭建一下整個服務架構,上面提到了,首先要拷貝兩個訂單服務,端口號分別爲 8002 和 8003,一起來對比看下三個訂單服務的配置文件。

8001 端口的訂單服務:

# 服務端口號
server:
  port: 8001

# 數據庫地址
datasource:
  url: localhost:3306/microservice01

spring:
  application:
    name: microservice-order # 對外暴露的服務名稱

  datasource: # 數據庫配置
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://${datasource.url}?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
    username: root
    password: 123456
    hikari:
      maximum-pool-size: 10 # 最大連接池數
      max-lifetime: 1770000

mybatis:
  # 指定別名設置的包爲所有entity
  type-aliases-package: com.itcodai.springcloud.entity
  mapper-locations: # mapper映射文件位置
    - classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true # 駝峯命名規範

# 客戶端註冊進eureka服務列表裏
eureka:
  client:
    service-url:
      defaultZone: http://eureka01:7001/eureka/,http://eureka02:7002/eureka/,http://eureka03:7003/eureka/,
  instance:
    instance-id: 書籍訂單服務-8001  # 人性化顯示出服務的信息
    prefer-ip-address: true    # 訪問路徑可顯示ip地址

# 使用actuator來展示項目的基本信息
info:
  author.name: shengwu ni
  app.name: microservice
  server.port: ${server.port}
  application.name: ${spring.application.name}

8002 端口的訂單服務:

# 服務端口號
server:
  port: 8002

# 數據庫地址
datasource:
  url: localhost:3306/microservice02

spring:
  application:
    name: microservice-order # 對外暴露的服務名稱

  datasource: # 數據庫配置
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://${datasource.url}?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
    username: root
    password: 123456
    hikari:
      maximum-pool-size: 10 # 最大連接池數
      max-lifetime: 1770000

mybatis:
  # 指定別名設置的包爲所有entity
  type-aliases-package: com.itcodai.springcloud.entity
  mapper-locations: # mapper映射文件位置
    - classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true # 駝峯命名規範

# 客戶端註冊進eureka服務列表裏
eureka:
  client:
    service-url:
      defaultZone: http://eureka01:7001/eureka/,http://eureka02:7002/eureka/,http://eureka03:7003/eureka/,
  instance:
    instance-id: 書籍訂單服務-8002  # 人性化顯示出服務的信息
    prefer-ip-address: true    # 訪問路徑可顯示ip地址

# 使用actuator來展示項目的基本信息
info:
  author.name: shengwu ni
  app.name: microservice
  server.port: ${server.port}
  application.name: ${spring.application.name}

8003 端口的訂單服務:

# 服務端口號
server:
  port: 8003

# 數據庫地址
datasource:
  url: localhost:3306/microservice03

spring:
  application:
    name: microservice-order # 對外暴露的服務名稱

  datasource: # 數據庫配置
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://${datasource.url}?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
    username: root
    password: 123456
    hikari:
      maximum-pool-size: 10 # 最大連接池數
      max-lifetime: 1770000

mybatis:
  # 指定別名設置的包爲所有entity
  type-aliases-package: com.itcodai.springcloud.entity
  mapper-locations: # mapper映射文件位置
    - classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true # 駝峯命名規範

# 客戶端註冊進eureka服務列表裏
eureka:
  client:
    service-url:
      defaultZone: http://eureka01:7001/eureka/,http://eureka02:7002/eureka/,http://eureka03:7003/eureka/,
  instance:
    instance-id: 書籍訂單服務-8003  # 人性化顯示出服務的信息
    prefer-ip-address: true    # 訪問路徑可顯示ip地址

# 使用actuator來展示項目的基本信息
info:
  author.name: shengwu ni
  app.name: microservice
  server.port: ${server.port}
  application.name: ${spring.application.name}

對比後發現,有幾個地方需要注意:

  1. 對外暴露的服務名稱必須要相同,因爲都是同一個服務,只不過有多個而已,因爲接下來Ribbon是通過服務名來調用服務的;
  2. 每個服務連接了不同的數據庫,這樣用來區分不同的服務,便於測試,實際中也可能是便於維護;
  3. 每個服務的個性化名稱展示可以區分一下,這樣在eureka裏可以很好的辨別出來

Eureka 集羣還是使用前面的 7001、7002 和 7003,首先我們啓動 Eureka 集羣,然後分別啓動 8001、8002 和 8003 三個訂單服務。(友情提示:這裏已經啓動了6個工程了,如果電腦的性能跟不上的話,可能已經開始卡頓了)

啓動了之後,可以訪問下 eureka01:7001,看下三個訂單服務是否正常註冊到 eureka 集羣裏。如下圖,說明集羣和訂單服務均正常。
eureka集羣

OK,接下來就是重點了,我們啓動服務消費方,也就是上一節中的訂單消費服務,然後在瀏覽器輸入 http://localhost:9001/consumer/order/get/1 即可查詢到對應的訂單服務:

{"id":1,"name":"跟武哥一起學 Spring Boot","price":39.99,"dbSource":"microservice03"}

刷新頁面,可以看到,結果如下:

{"id":1,"name":"跟武哥一起學 Spring Boot","price":39.99,"dbSource":"microservice01"}

再刷新頁面,可以看到,結果如下:

{"id":1,"name":"跟武哥一起學 Spring Boot","price":39.99,"dbSource":"microservice02"}

可以看到,dbsource的值一在 microservice01、microservice02 和 microservice03 之間輪詢切換(這個值是我在三個數據庫中設置的不同的值,就是爲了在這展示,方便看到效果),這就說明了,Ribbon 的負載均衡已經起作用了,客戶端會輪詢的根據服務名,從 8001、8002 和 8003 之間切換訪問,從而達到負載均衡的效果。

同時,也可以看到,Ribbon 的默認負載均衡算法是輪詢。

2. 如何指定 Ribbon 的負載均衡策略

由上面的結果可知,Ribbon 默認的策略是輪詢,那麼 Ribbon 除了輪詢,還有哪些負載均衡的策略呢?我們如何去設置自己想要的策略呢?

Ribbon 自帶的負載均衡策略有如下幾個:

  1. RoundRibbonRule:輪詢。人人有份,一個個來!
  2. RandomRule:隨機。拼人品了!
  3. AvailabilityFilteringRule:先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,以及併發連接數超過閾值的服務,剩下的服務,使用輪詢策略。
  4. WeightedResponseTimeRule:根據平均響應時間計算所有服務的權重,響應越快的服務權重越高,越容易被選中。一開始啓動時,統計信息不足的情況下,使用輪詢。
  5. RetryRule:先輪詢,如果獲取失敗則在指定時間內重試,重新輪詢可用的服務。
  6. BestAvailableRule:先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然後選擇一個併發量最小的服務。
  7. ZoneAvoidanceRule:複合判斷 server 所在區域的性能和 server 的可用性選擇服務器

如何指定 Ribbon 自帶的負載均衡策略呢?我們需要在配置類中指定一下即可,如下:

/**
 * 配置RestTemplate
 * @author shengwu ni
 */
@Configuration
public class RestTemplateConfig {

    /**
     * '@LoadBalanced'註解表示使用Ribbon實現客戶端負載均衡
     * @return RestTemplate
     */
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    /**
     * 指定其他負載均衡策略
     * @return IRule
     */
    @Bean
    public IRule myRule() {
        // 指定重試策略:隨機策略
        return new RandomRule();
    }
}

我們可以 new 出以上對應的策略,來實現對應的負載均衡,讀者可以 new RandomRule() 測試一下隨機策略,然後重複刷新上面的測試地址,可以發現是隨機請求三個服務。其他的策略,讀者可以自行嘗試一下。

源碼下載地址:https://gitee.com/eson15/springcloud_study
更多優質文章請關注我的微信公衆號【程序員私房菜】,回覆“資源”和“架構”可以領取優質的視頻學習資源。
程序員私房菜

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章