看看大牛是怎麼理解微服務閘道器與使用者身份識別,建立Zuul閘道器服務

Zuul的基礎使用

Zuul是Netflix公司的開源閘道器產品,可以和Eureka、Ribbon、Hystrix等元件配合使用。Zuul的規則引擎和過濾器基本上可以用任何JVM語言編寫,內建支援Java和Groovy。

在Spring Cloud框架中,Zuul的角色是閘道器,負責接收所有的REST請求(如網頁端、App端等),然後進行內部轉發,是微服務提供者叢集的流量入口。本書將Zuul稱為內部閘道器,以便和Nginx外部閘道器相區分。

Zuul的功能大致有:

(1)路由:將不同REST請求轉發至不同的微服務提供者,其作用類似於Nginx的反向代理。同時,也起到了統一埠的作用,將很多微服務提供者的不同埠統一到了Zuul的服務埠。

(2)認證:閘道器直接暴露在公網上時,終端要呼叫某個服務,通常會把登入後的token(令牌)傳過來,閘道器層對token進行有效性驗證。如果token無效(或沒有token),就不允許訪問REST服務。可以結合Spring Security中的認證機制完成Zuul閘道器的安全認證。

(3)限流:高併發場景下瞬時流量不可預估,為了保證服務對外的穩定性,限流成為每個應用必備的一道安全防火牆。如果沒有這道安全防火牆,那麼請求的流量超過服務的負載能力時很容易造成整個服務的癱瘓。

(4)負載均衡:在多個微服務提供者之間按照多種策略實現負載均衡。

建立Zuul閘道器服務

Spring Cloud對Zuul進行了整合與增強。Zuul作為閘道器層,自身也是一個微服務,跟其他服務提供者一樣都註冊在Eureka Server上,可以相互發現。Zuul能感知到哪些Provider例項線上,同時透過配置路由規則可以將REST請求自動轉發到指定的後端微服務提供者。

新建Zuul閘道器服務專案時需要在啟動類中添加註解@EnableZuulProxy,宣告這是一個閘道器服務提供者。當然,也需要在pom。xml檔案中手動新增如下依賴:

org。springframework。cloud spring-cloud-starter-netflix-zuul

啟動類的程式碼如下:

package com。crazymaker。springcloud。cloud。center。zuul;。。。@EnableAutoConfiguration(exclude = {SecurityAutoConfiguration。class})@SpringBootApplication(scanBasePackages = {“com。crazymaker。springcloud。cloud。center。zuul”, “com。crazymaker。springcloud。standard”, “com。crazymaker。springcloud。user。info。contract” })@EnableScheduling@EnableHystrix@EnableDiscoveryClient//開啟閘道器服務@EnableZuulProxy@EnableCircuitBreakerpublic class ZuulServerApplication { public static void main(String[] args) { SpringApplication。run(ZuulServerApplication。class, args); }}

Zuul路由規則配置

作為反向代理,Zuul需要透過路由規則將REST請求轉發到上游的微服務Provider。作為示例,下面列出crazy-springcloud腳手架中Zuul閘道器的路由規則配置:

#服務閘道器配置zuul: ribbonIsolationStrategy: THREAD host: connect-timeout-millis: 600000 socket-timeout-millis: 600000 #路由規則 routes: seckill-provider: path: /seckill-provider/** serviceId: seckill-provider strip-prefix: false message-provider: path: /message-provider/** serviceId: message-provider strip-prefix: false user-provider: path: /user-provider/** serviceId: user-provider strip-prefix: false backend-provider: path: /backend-provider/** serviceId: backend-provider strip-prefix: false generate-provider: path: /generate-provider/** serviceId: generate-provider strip-prefix: false sensitiveHeaders: Cookie,Set-Cookie,token,backend,Authorization demo-provider: path: /demo-provider/** serviceId: demo-provider strip-prefix: false urlDemo: path: /blog/** url: https://www。cnblogs。com sensitiveHeaders: Cookie,Set-Cookie,token,backend,Authorization

以上示例中,有兩種方式的路由規則配置:

(1)路由到直接URL;

(2)路由到微服務提供者。

先看第一種方式的路由規則配置:路由到直接URL。在上述示例中,有一條名為urlDemo的路由規則,該規則匹配到格式為/blog/**的所有URL請求,直接轉發到

https://www。cnblogs。com

的地址上。

比如,透過閘道器訪問如下URL:

http://127。0。0。1:7799/blog/crazymakercircle/p/9904544。html

此URL滿足/blog/**的匹配規則,將被Zuul直接轉發到上游的URL地址:

https://www。cnblogs。com/crazymakercircle/p/9904544。html

修改地址為瘋狂創客圈的社群部落格的實際地址,在瀏覽器中看到的Zuul轉發結果如圖6-2所示。

看看大牛是怎麼理解微服務閘道器與使用者身份識別,建立Zuul閘道器服務

圖6-2 Zuul直接轉發到上游的URL地址

再看第二種方式的路由規則配置:路由到微服務提供者。

比如在上述程式碼中,有一條名為user-provider的路由規則,該規則將匹配/user-provider/**的所有URL請求,直接路由到名為user-provider的某個微服務提供者。

兩種方式的區別如下:

(1)第一種方式使用url屬性來指定直接的上游URL的字首;第二種方式使用serviceId屬性來指定上游服務提供者的名稱。

(2)第二種方式需要結合Eureka Client客戶端來實現動態的路由轉發功能,啟動類需要加上註解@EnableDiscoveryClient,只能用於Spring Cloud架構中。其實該註解也可以不加,因為網關注解@EnableZuulProxy已經預設進行了匯入。

使用第二種方式,配置檔案中增加Eureka Client客戶端的相關配置如下:

eureka: client: serviceUrl: defaultZone: http://${EUREKA_ZONE_HOST:localhost}:7777/eureka/ instance: prefer-ip-address: true #訪問路徑可以顯示IP地址 instance-id: ${spring。cloud。client。ip-address}:${server。port} ip-address: ${spring。cloud。client。ip-address}

過濾敏感請求頭部

在同一個系統中,在不同Provider之間共享請求頭是可行的,但是,如果Zuul需要將請求轉發到外部,可能不希望敏感的請求頭洩露到外部的其他伺服器。

防止請求頭洩露的方式之一是,在Zuul的路由配置中指定要忽略的請求頭列表,並且多個敏感頭部之間可以用逗號隔開。下面是一個簡單的例項:

spring: application: name: cloud-zuulzuul: sensitiveHeaders: Cookie,Set-Cookie,token,backend,Authorization

大家知道,Cookie經常用於在流量中快取使用者的會話、使用者憑證等資訊,對於外部系統而言是需要保密的,所以應該設定為敏感標題,不應該帶往系統外部。

預設情況下,Zuul轉發請求時會把header清空,如果在微服務叢集內部轉發請求,上游Provider就會收不到任何頭部。如果需要傳遞原始的header資訊到最終的上游,就需要新增如下敏感頭部設定:

zuul。sensitive-headers=

上面配置了敏感頭部為空,YML格式的配置也需要進行空配置,表示沒有需要遮蔽的頭部。上面是全域性配置,也可對單個路由規則進行區域性配置,格式如下:zuul。routes。xxxapi-xxx。sensitiveHeaders=比如crazy-springcloud腳手架中專門對外部的轉發規則urlDemo進行了請求頭的遮蔽,它的配置如下:

#服務閘道器路由規則zuul: routes: urlDemo: path: /blog/** url: https://www。cnblogs。com sensitiveHeaders: Cookie,Set-Cookie,token,backend,Authorization

對於該規則自身而言,單個路由規則的區域性配置會覆蓋全域性的設定。

路徑字首的處理

如果不進行任何配置,預設情況下Zuul會去掉路由的路徑字首。

例如,從客戶端發起一個請求:

http://crazydemo。com:7799/demo-provider/api/demo/hello/v1

在Zuul進行路由處理時,會去掉在路由規則清單中配置的路徑字首demo-provider。處理之後,轉發到上游的服務提供者的URL將變成下面的樣子:

http://{provider-ip}:{provider-port}/api/demo/hello/v1

如果上游的微服務提供者沒有配置路徑字首,Zuul的這種預設處理和轉發就不會有問題。但是,如果上游提供者配置了統一的路徑字首,而字首被去掉,上游服務提供者就會報出404的錯誤,也就是找不到URL對應的資源。

比如,在crazy-springcloud腳手架中的所有服務提供者都是配有context-path路徑字首的,如此配置的優勢之一是會使下游Nginx外部閘道器進行代理轉發時更加靈活。

從微服務demo-provider的配置檔案src/main/resources/bootstrap。yml可以看出,它的context-path路徑字首為/demo-provider,具體配置內容如下:

server: port: 7700 servlet: context-path: /demo-provider

在Zuul進行路由處理時,如何保留請求URL中的路徑字首呢?具體來說,可以設定配置項stripPrefix的值為false,確保路徑字首不會擷取掉。stripPrefix的值預設為true。

demo-provider的路由規則具體如下:

#服務閘道器路由規則zuul: routes: demo-provider: path: /demo-provider/** serviceId: demo-provider strip-prefix: false

本文給大家講解的內容是 微服務閘道器與使用者身份識別,建立Zuul閘道器服務

下篇文章給大家講解的是SpringCloudRPC遠端呼叫核心原理:微服務閘道器與使用者身份識別,Zuul過濾器;

覺得文章不錯的朋友可以轉發此文關注小編;

感謝大家的支援!