Spring Cloud(六):服務網關zuul


通過前面幾篇文章的介紹,Spring Cloud微服務架構可通過Eureka實現服務注冊與發現,通過Ribbon或Feign來實現服務間的負載均衡調用,通過Hystrix來為服務調用提供服務降級、熔斷機制避免雪崩效應,通過Spring Cloud Config實現服務配置的集中化管理。微服務架構內部管理的基本組件差不多都已涵蓋了,但是我們的服務最終是需要提供給客戶端訪問的,客戶端如何來訪問這些微服務,就需要引入一個叫服務網關的組件了。

zuul

zuul是netflix提供的一個基於JVM的路由與服務端負載均衡器。它在客戶端與后端服務之間建立了一道關卡,客戶端所有請求必須經過zuul轉發到后端對應的微服務,返回結果再經由zuul返回給客戶端。zuul與Eureka,Config組合的基本結構如圖

zuul

zuul作為Eureka Client從Eureka Server獲取其它微服務的配置信息,從而可以將客戶端請求通過Service ID來負載均衡地轉發到后端的服務實例,同時也作為Config Client從Config Server獲取自身所需的配置信息。

在netflix內部,zuul被用來實現安全認證、動態路由、反向代理、服務遷移、服務削峰、壓力測試、金絲雀測試(灰度發布測試)等功能。本文介紹zuul的基本使用與路由規則。

基本使用

創建maven項目 springcloud-zuul

1.pom.xml中引入依賴 spring-cloud-starter-netflix-zuul

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

2.application.yml配置文件中添加必要的配置,主要是eureka客戶端配置

spring:
  application:
    name: zuul-server

server:
  port: 8765

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

3.啟動類添加注解 @EnableZuulProxy

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class, args);
    }
}

一如既往的簡單,Spring Cloud之所以流行就是因為它基於Spring Boot將一些通用的功能進行了開箱即用的封裝,使得開發者簡單幾步就能快速集成一個微服務框架。

依次啟動前文所創建的springcloud-eureka, springcloud-config, springcloud-eureka-client, springcloud-zuul,http://localhost:8765/hello-service/hello 返回 Hello, welcome to spring cloud. env: hello-service-dev, value: hello-service-dev 可見通過zuul的請求轉發到了hello-service。

為了驗證zuul轉發請求具備負載均衡的能力,可以將springcloud-eureka-client 中的hello接口返回值做一些調整,並改變端口重啟一個實例,再次請求http://localhost:8765/hello-service/hello 將能看到返回結果在兩者之間切換。

以上配置文件中並沒有加任何路由配置,zuul是怎么將請求正確轉發到對應的微服務的呢? 請看下面的路由規則。

路由規則

1.默認路由規則

zuul提供了默認的路由規則,不需要任何配置就會默認將注冊的服務進行路徑映射。我們可以通過actuator提供的接口來查看,在application.yml中添加配置

management:
  endpoints:
    web:
      exposure:
        include: "*"

放開actuator的其它接口訪問(默認只放開了/info 與/health接口), 瀏覽器中訪問 http://localhost:8765/actuator/routes, 可以看到返回的zuul默認的路由映射關系

zuul-route

zuul默認將 /service-id/** 的請求路由到Service ID(即spring.application.name的值)為 service-id的服務,如 /hello-service/hello,將轉發到hello-service服務的/hello接口。

2.自定義路由規則

我們看到zuul的默認路由規則將config-server也映射出來了,對於這類內部服務我們不希望暴露,則可以通過 zuul.ignoredServices 來進行屏蔽,在application.yml配置文件中添加

zuul:
  ignored-services: "config-server"

重啟,再次查看http://localhost:8765/actuator/routes , config-server已經被屏蔽了。

通過zuul.routes可添加自定義路由,可以有 zuul.routes.{route-name}.path + zuul.routes.{route-name}.serviceId或urlzuul.routes.{service-id}: path 兩個格式, 如下

zuul:
  ignored-services: "config-server"
  routes:
    hello:
      path: /hi/**
      serviceId: hello-service
    hello-service: /hi2/**
    jboost:
      path: /jboost/**
      url: http://blog.jboost.cn

訪問 http://localhost:8765/hi/hellohttp://localhost:8765/hi2/hello 都將路由到 hello-service的hello接口,訪問 http://localhost:8765/jboost/ 將訪問到jboost博客首頁。添加自定義路由后,默認路由仍然存在, 你仍然可以通過 http://localhost:8765/hello-service/hello 來訪問 hello-service的hello接口。

默認的路由規則將Service ID作為匹配路徑,看起來有點長,我們想將匹配路徑縮短一點,比如hello-service的匹配路徑想改為 /hello/**, 而不是/hello-service/**, 如果像上面配置,一個微服務系統可能涉及幾十甚至上百個服務,那配置起來將是一場噩夢。別急, zuul提供了 ServiceRouteMapper 接口來解決這一問題,其中 PatternServiceRouteMapper 可以基於正則表達式來進行路由抽取。

創建一個配置類,注入一個 PatternServiceRouteMapper 的bean,如下

@Configuration
public class ZuulConfiguration {

    @Bean
    public PatternServiceRouteMapper serviceRouteMapper() {
        return new PatternServiceRouteMapper(
                "(?<name>^.+)-(?<postfix>.+$)",
                "${name}");
    }
}

該實現將會對所有服務的路由進行調整,service id 形如 name-postfix的匹配路徑為 /name/**, 如hello-service 匹配 /hello/**。 如果正則表達式匹配失敗,則還是以默認規則進行路由,如果匹配成功,則默認規則失效,但在配置文件中定義的路由仍然有效。上述驗證中,你都可以通過 http://localhost:8765/actuator/routes 來查看當前生效的路由。

其它配置

zuul使用Ribbon來定位服務實例,所有請求都在hystrix command里執行,所以在zuul中可以添加Ribbon, Hystrix相關配置(具體參考前面Ribbon、Hystrix相關文章)

  • zuul.ignoredPatterns 對某些路徑進行屏蔽,如 /**/admin/** 將會屏蔽所有路徑中包含admin的接口訪問
  • zuul.sensitiveHeaders 對一些header進行過濾,不傳遞給后端服務,默認包括Cookie,Set-Cookie,Authorization, 如果要讓zuul發送所有header,則需要顯式地將sensitiveHeaders置空值
  • zuul.prefix 為所有映射添加前綴,如/api, 這樣route里配的 /myusers/** 就能匹配客戶端請求的/api/myusers/**。默認zuul代理在轉發時,前綴會被移除,通過設置zuul.stripPrefix=false可不移除

總結

本文簡單介紹了zuul的基本使用與路由規則,更高階的應用我們后面繼續。
認真生活,快樂分享
歡迎關注微信公眾號:空山新雨的技術空間
獲取Spring Boot,Spring Cloud,Docker等系列技術文章
公眾號二維碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM