當前位置:
首頁 > 最新 > springcloud:服務網關Zuul高級篇

springcloud:服務網關Zuul高級篇

時間過的很快,寫springcloud(十):服務網關zuul初級篇還在半年前,現在已經是2018年了,我們繼續探討Zuul更高級的使用方式。

上篇文章主要介紹了Zuul網關使用模式,以及自動轉發機制,但其實Zuul還有更多的應用場景,比如:鑒權、流量轉發、請求統計等等,這些功能都可以使用Zuul來實現。


Zuul的核心

Filter是Zuul的核心,用來實現對外服務的控制。Filter的生命周期有4個,分別是「PRE」、「ROUTING」、「POST」、「ERROR」,整個生命周期可以用下圖來表示。

Zuul大部分功能都是通過過濾器來實現的,這些過濾器類型對應於請求的典型生命周期。

PRE:這種過濾器在請求被路由之前調用。我們可利用這種過濾器實現身份驗證、在集群中選擇請求的微服務、記錄調試信息等。

ROUTING:這種過濾器將請求路由到微服務。這種過濾器用於構建發送給微服務的請求,並使用Apache HttpClient或Netfilx Ribbon請求微服務。

POST:這種過濾器在路由到微服務以後執行。這種過濾器可用來為響應添加標準的HTTP Header、收集統計信息和指標、將響應從微服務發送給客戶端等。

ERROR:在其他階段發生錯誤時執行該過濾器。 除了默認的過濾器類型,Zuul還允許我們創建自定義的過濾器類型。例如,我們可以定製一種STATIC類型的過濾器,直接在Zuul中生成響應,而不將請求轉發到後端的微服務。


禁用指定的Filter

可以在application.yml中配置需要禁用的filter,格式:


實現自定義Filter,需要繼承ZuulFilter的類,並覆蓋其中的4個方法。


我們假設有這樣一個場景,因為服務網關應對的是外部的所有請求,為了避免產生安全隱患,我們需要對請求做一定的限制,比如請求中含有Token便讓請求繼續往下走,如果請求不帶Token就直接返回並給出提示。

首先自定義一個Filter,在run()方法中驗證參數是否含有Token。

將TokenFilter加入到請求攔截隊列,在啟動類中添加以下代碼:

這樣就將我們自定義好的Filter加入到了請求攔截中。

測試

我們依次啟動示例項目: 、 、 ,這個三個項目均為上一篇示例項目, 稍微進行改造。

訪問地址: ,返回:token is empty ,請求被攔截返回。

訪問地址: ,返回:hello neo,this is first messge,說明請求正常響應。

通過上面這例子我們可以看出,我們可以使用「PRE"類型的Filter做很多的驗證工作,在實際使用中我們可以結合shiro、oauth2.0等技術去做鑒權、驗證。


當我們的後端服務出現異常的時候,我們不希望將異常拋出給最外層,期望服務可以自動進行一降級。Zuul給我們提供了這樣的支持。當某個服務出現異常時,直接返回我們預設的信息。

我們通過自定義的fallback方法,並且將其指定給某個route來實現該route訪問出問題的熔斷處理。主要繼承ZuulFallbackProvider介面來實現,ZuulFallbackProvider默認有兩個方法,一個用來指明熔斷攔截哪個服務,一個定製返回內容。

實現類通過實現getRoute方法,告訴Zuul它是負責哪個route定義的熔斷。而fallbackResponse方法則是告訴 Zuul 斷路出現時,它會提供一個什麼返回值來處理請求。

後來Spring又擴展了此類,豐富了返回方式,在返回的內容中添加了異常信息,因此最新版本建議直接繼承類 。

我們以上面的spring-cloud-producer服務為例,定製它的熔斷返回內容。

當服務出現異常時,列印相關異常信息,並返回"The service is unavailable."。

啟動項目spring-cloud-producer-2,這時候服務中心會有兩個spring-cloud-producer項目,我們重啟Zuul項目。再手動關閉spring-cloud-producer-2項目,多次訪問地址: ,會交替返回:

根據返回結果可以看出:spring-cloud-producer-2項目已經啟用了熔斷,返回:

Zuul 目前只支持服務級別的熔斷,不支持具體到某個URL進行熔斷。


有時候因為網路或者其它原因,服務可能會暫時的不可用,這個時候我們希望可以再次對服務進行重試,Zuul也幫我們實現了此功能,需要結合Spring Retry 一起來實現。下面我們以上面的項目為例做演示。

添加Spring Retry依賴

首先在spring-cloud-zuul項目中添加Spring Retry依賴。

開啟Zuul Retry

再配置文件中配置啟用Zuul Retry

這樣我們就開啟了Zuul的重試功能。

測試

我們對spring-cloud-producer-2進行改造,在hello方法中添加定時,並且在請求的一開始列印參數。

重啟 spring-cloud-producer-2和spring-cloud-zuul項目。

訪問地址: ,當頁面返回: 時查看項目spring-cloud-producer-2後台日誌如下:

說明進行了三次的請求,也就是進行了兩次的重試。這樣也就驗證了我們的配置信息,完成了Zuul的重試功能。

注意

開啟重試在某些情況下是有問題的,比如當壓力過大,一個實例停止響應時,路由將流量轉到另一個實例,很有可能導致最終所有的實例全被壓垮。說到底,斷路器的其中一個作用就是防止故障或者壓力擴散。用了retry,斷路器就只有在該服務的所有實例都無法運作的情況下才能起作用。這種時候,斷路器的形式更像是提供一種友好的錯誤信息,或者假裝服務正常運行的假象給使用者。

不用retry,僅使用負載均衡和熔斷,就必須考慮到是否能夠接受單個服務實例關閉和eureka刷新服務列表之間帶來的短時間的熔斷。如果可以接受,就無需使用retry。


我們實際使用Zuul的方式如上圖,不同的客戶端使用不同的負載將請求分發到後端的Zuul,Zuul在通過Eureka調用後端服務,最後對外輸出。因此為了保證Zuul的高可用性,前端可以同時啟動多個Zuul實例進行負載,在Zuul的前端使用Nginx或者F5進行負載轉發以達到高可用性。

示例代碼:https://github.com/ityouknow/spring-cloud-examples


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 純潔的微笑 的精彩文章:

TAG:純潔的微笑 |