跟我學Spring Cloud(Finchley版)-16-Zuul

至此,已實現基於Eureka的服務發現,基於Ribbon的負載均衡,Feign也爲咱們提供了很不錯的遠程調用能力,使用Hystrix後,高併發場景下應用也不會被別人拖死——我們的微服務架構已經日趨完善!git

然而,迄今爲止,只討論了微服務之間的調用,尚沒討論如何應對外部請求。應對外部請求時,就會發現,咱們的架構依然存在一些問題——github

爲何要使用網關

不一樣的微服務通常會有不一樣的網絡地址,而外部客戶端(例如手機APP)可能須要調用多個服務的接口才能完成一個業務需求。例如一個電影購票的手機APP,可能會調用多個微服務的接口,才能完成一次購票的業務流程,以下圖所示。web

用戶請求多個微服務

若是讓客戶端直接與各個微服務通訊,會有如下的問題:spring

  • 客戶端會屢次請求不一樣的微服務,增長了客戶端的複雜性。
  • 存在跨域請求,在必定場景下處理相對複雜。
  • 認證複雜,每一個服務都須要獨立認證。
  • 難以重構,隨着項目的迭代,可能須要從新劃分微服務。例如,可能將多個服務合併成一個或者將一個服務拆分紅多個。若是客戶端直接與微服務通訊,那麼重構將會很難實施。
  • 某些微服務可能使用了防火牆/瀏覽器不友好的協議,直接訪問會有必定的困難。

以上問題可藉助微服務網關解決。微服務網關是介於客戶端和服務器端之間的中間層,全部的外部請求都會先通過微服務網關。使用微服務網關後,架構以下所示。數據庫

圖8-2 使用微服務網關

此時,微服務網關封裝了應用程序的內部結構,客戶端只須跟網關交互,而無須直接調用特定微服務的接口。這樣,開發就能夠獲得簡化。不只如此,使用微服務網關還有如下優勢:後端

  • 易於監控。可在微服務網關收集監控數據並將其推送到外部系統進行分析。
  • 易於認證。可在微服務網關上進行認證,而後再將請求轉發到後端的微服務,而無須在每一個微服務中進行認證。
  • 減小了客戶端與各個微服務之間的交互次數。

Zuul簡介

Zuul是Netflix開源的微服務網關,它能夠和Eureka、Ribbon、Hystrix等組件配合使用。Zuul的核心是一系列的過濾器,這些過濾器幫助咱們完成如下功能:跨域

  • 身份認證與安全:識別每一個資源的驗證要求,並拒絕那些與要求不符的請求;
  • 審查與監控:在邊緣位置追蹤有意義的數據和統計結果,從而爲咱們帶來精確的生產視圖;
  • 動態路由:動態地將請求路由到不一樣的後端集羣;
  • 壓力測試:逐漸增長指向集羣的流量,以瞭解性能;
  • 負載分配:爲每一種負載類型分配對應容量,並棄用超出限定值的請求;
  • 靜態響應處理:在邊緣位置直接創建部分響應,從而避免其轉發到內部集羣;
  • 多區域彈性:跨越AWS Region進行請求路由,旨在實現ELB(Elastic Load Balancing)使用的多樣化;以及讓系統的邊緣更貼近系統的使用者。

注1:以上介紹來自Zuul官方文檔,但其實開源版本的Zuul以上功能一個都沒有——開源的Zuul只是幾個Jar包而已,以上能力指的應該是Netflix官方自用的Zuul的能力。瀏覽器

注2:Netflix自用的Zuul能力是比較強大的,可以使用Groovy編寫過濾器,而且可動態加載/卸載、修改規則,並且使用Cassandra做爲數據庫,然而開源版本這些一個都沒有安全

注3:Spring Cloud中,Zuul絕大部分功能都是Spring Cloud團隊爲Zuul開發的服務器

注4:因此Zuul 2.x的開源進度延後一年,Spring Cloud團隊開發了本身的Spring Cloud Gateway,並宣佈Spring Cloud不打算支持Zuul 2.x,你還以爲意外嗎?

注5:看到這裏,不少人可能沒有動力學習Zuul了,我的認爲仍是能夠了解一下的,後面講到Spring Cloud Gateway時,你會發現不少設計理念是相通的。

Spring Cloud對Zuul進行了整合與加強。目前,Zuul使用的默認HTTP客戶端是Apache HTTP Client,也可使用RestClient或者okhttp3.OkHttpClient 。 若是想要使用RestClient,能夠設置ribbon.restclient.enabled=true ;想要使用okhttp3.OkHttpClient ,能夠設置ribbon.okhttp.enabled=true

TIPS

Zuul的GitHub:https://github.com/Netflix/zuul

入門

下面經過一個簡單的例子幫助你們快速入門Zuul。

編碼

  • 加依賴

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
  • 加註解:@EnableZuulProxy

  • 寫配置:

    server:
      port: 8040
    spring:
      application:
        name: microservice-gateway-zuul
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/

由代碼可知,咱們編寫了一個Zuul,並將其註冊到了Eureka上。

測試

準備工做

啓動多個應用,Eureka Server上展現以下:

Eureka首頁

反向代理測試

  • 訪問http://127.0.0.1:8040/microservice-provider-user/users/1 ,會發現請求被轉發到了microservice-provider-user 服務的/users/1 端點;
  • 訪問http://127.0.0.1:8040/microservice-consumer-movie/movies/users/1 ,發現請求被轉發到了microservice-consumer-movie 服務的/movies/users/1 端點;

負載均衡測試

屢次訪問訪問http://127.0.0.1:8040/microservice-provider-user/users/1 ,會發現兩個microservice-provider-user 都會打印相似以下的日誌:

Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.balance as balance3_0_0_, user0_.name as name4_0_0_, user0_.username as username5_0_0_ from user user0_ where user0_.id=?
...

斷路器測試

application.yml 中添加以下配置後,並重啓Zuul:

management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-details: always

此時,此時訪問http://localhost:8040/actuator/health ,可看到相似以下結果:

{
  ...
  "hystrix":{"status":"UP"}
}

而且,當Zuul轉發API後,訪問http://localhost:8040/actuator/hystrix.stream 可看到相似以下的信息:

data: {"type":"HystrixCommand","name":"microservice-provider-user",.....}

說明Zuul整合了Hystrix。

配套代碼

本文首發

http://www.itmuch.com/spring-cloud/finchley-16/

乾貨分享

全是乾貨!

相關文章
相關標籤/搜索