本系列為之前系列的整理重啟版,隨著專案的發展以及專案中的使用,之前系列裡面很多東西發生了變化,並且還有一些東西之前系列並沒有提到,所以重啟這個系列重新整理下,歡迎各位留言交流,謝謝!~
之前我們提到了,不同的叢集,使用的是同一套 Eureka 叢集。
我們會動態線上釋出每個微服務,在 K8s 的環境下,我們一般使用 ReplicaSet 將我們的微服務部署成無狀態的微服務例項(參考:ReplicaSet);在這種情況下,新的微服務例項地址(ip)和原來的地址一般是不一樣的。在這種情況下,我們想實現例項的快速上下線,即快速感知例項狀態。
這需要兩方面的配置,一是 Eureka 客戶端與例項配置,另一個就是這裡要討論的 Eureka 伺服器的配置。在正常釋出的過程中,我們會先啟動一個新的例項,然後優雅關閉一個老例項,然後再啟動一個新的,再關閉一個老的,以此類推,滾動更新。優雅關閉的時候,一般會從註冊中心 Eureka 登出自己。但是有異常情況的時候,例如 JVM Stop-the-world,或者死鎖等,優雅關閉可能失敗。還有就是這些異常也可能導致心跳無法正常傳送到 Eureka。
所以為了實現例項狀態快速被其他例項感知,我們需要啟動Eureka 主動例項過期檢查,同時,建議關閉掉自我保護機制。主要因為:自我保護主要針對叢集中網路出現問題,或者 Eureka 出現問題導致 Stop-the-world 並且無法恢復,或者壓力過大,導致有很多例項無法傳送心跳導致很多例項狀態異常,但是實際例項還在正常工作的情況,不要讓這些例項不參與負載均衡。啟用自我保護的情況下,就會停止對於例項的過期。但是,如果出現這種情況,其實也代表很多例項無法讀取註冊中心了。並且還有一種情況就是,Eureka 重啟,雖然不常見,但是對於映象中其他的元件更新(例如 JDK 等)我們還是很頻繁的。在我們的叢集中, Eureka 叢集壓力不大(服務幾百個例項),並且 Eureka 比較穩定,其實只需要考慮 Eureka 網路出問題的情況。我傾向於從客戶端對於例項快取機制來解決這個問題,如果返回例項列表為空,則使用上次的例項列表進行負載均衡,這樣既能解決 Eureka 重啟的情況,又能處理一些 Eureka 網路隔離的情況。
對於 API 閘道器,我們使用 Spring Cloud Gatway。Spring Cloud Gateway 是基於 WebFlux(底層即 Project Reactor,基於 Netty 實現)的 API 閘道器。我們在使用的過程中,遇到並解決了以下一些問題:
- Spring Cloud Gateway 是純非同步響應式的程式碼實現,API 閘道器涉及介面 Body 加密:我們需要對發過來的請求進行解密再發往微服務,之後對微服務返回的響應進行加密再返回給客戶端,這就涉及到了 Body 讀取與修改。在 Spring Cloud Gateway 中如何實現 Body 的讀取與修改呢?這塊要好好考慮實現,並且保證不能有記憶體洩漏。
- API 閘道器需要鑑權,但是鑑權一般是單獨有另一個微服務負責,API 閘道器需要呼叫這個微服務,如何在非同步的環境下呼叫呢?
- 發往微服務的每個請求,都是非同步響應非阻塞的,所以可以不像微服務呼叫微服務那樣做執行緒隔離,限流也可以不使用客戶端限流,而是每個微服務自己限流。
- 發往微服務的每個請求,是需要有重試機制的。
- 發往微服務的每個請求,也需要做例項和路徑級別的斷路機制。
本小節我們繼續針對註冊中心 Eureka 以及 API 閘道器需要考慮的異常情況,設計問題等做了詳細的說明與分析。接下來我們將開始入手開始開發我們的框架專案。
微信搜尋“我的程式設計喵”關注公眾號,每日一刷,輕鬆提升技術,斬獲各種offer: