上篇文章《Eureka 緩存機制》介紹了Eureka的緩存機制,相信你們對Eureka 有了進一步的瞭解,本文將詳細介紹API網關如何實現服務下線的實時感知。算法
在基於雲的微服務應用中,服務實例的網絡位置都是動態分配的。並且因爲自動伸縮、故障和升級,服務實例會常常動態改變。所以,客戶端代碼須要使用更加複雜的服務發現機制。數據庫
目前服務發現主要有兩種模式:客戶端發現和服務端發現。緩存
客戶端發現相對於服務端發現最大的區別是:客戶端知道(緩存)可用服務註冊表信息。若是Client端緩存沒能從服務端及時更新的話,可能出現Client 與 服務端緩存數據不一致的狀況。安全
Netflix OSS 提供了一個客戶端服務發現的好例子。Eureka Server 爲註冊中心,Zuul 相對於Eureka Server來講是Eureka Client,Zuul 會把 Eureka Server 端服務列表緩存到本地,並以定時任務的形式更新服務列表,同時zuul經過本地列表發現其它服務,使用Ribbon實現客戶端負載均衡。網絡
正常狀況下,調用方對網關發起請求即刻能獲得響應。可是當對生產者作縮容、下線、升級的狀況下,因爲Eureka這種多級緩存的設計結構和定時更新的機制,LoadBalance 端的服務列表B存在更新不及時的狀況(由上篇文章《Eureka 緩存機制》可知,服務消費者最長感知時間將無限趨近240s),若是這時消費者對網關發起請求,LoadBalance 會對一個已經不存在的服務發起請求,請求是會超時的。負載均衡
生產者下線後,最早獲得感知的是 Eureka Server 中的 readWriteCacheMap,最後獲得感知的是網關核心中的 LoadBalance。可是 loadBalance 對生產者的發現是在 loadBalance 本地維護的列表中。異步
因此要想達到網關對生產者下線的實時感知,能夠這樣作:首先生產者或者部署平臺主動通知 Eureka Server, 而後跳過 Eureka 多級緩存之間的更新時間,直接通知 Zuul 中的 Eureka Client,最後將 Eureka Client 中的服務列表更新到 Ribbon 中。ide
可是若是下線通知的邏輯代碼放在生產者中,會形成代碼污染、語言差別等問題。微服務
借用一句名言:設計
「計算機科學領域的任何問題均可以經過增長一個間接的中間層來解決」
Gateway-SynchSpeed 至關於一個代理服務,它對外提供REST API來負責響應調用方的下線請求,同時會將生產者的狀態同步到 Eureka Server 和 網關核心,起着 狀態同步 和 軟事物 的做用。
思路:在生產者作 縮容、下線、升級 前,spider 平臺(spider爲容器管理平臺)會主動通知 Gateway-SynchSpeed 某個生產者的某個實例要下線了,而後 Gateway-SynchSpeed 會通知 Eureka Server 生產者的某個實例下線了;若是Eureka Server 下線成功,Gateway-SynchSpeed 會直接通知 網關核心。
設計特色
無侵入性、方便使用。不用關心調用方的基於何種語言實現,調用者只要對 Gateway-SynchSpeed 發起一個http rest請求便可,真正的實現邏輯不用侵入到調用方而是交給這個代理來實現。
原子性。調用方先在Eureka Server下線,而後在全部相關網關核心中下線爲最小工做執行單元,Gateway-SynchSpeed 至關於一個"軟事物",保證服務下線的某種程度上原子特性。
步驟說明
第一步:在生產者作 縮容、下線、升級 前,spider平臺會以http請求的形式通知到 Gateway-SynchSpeed 服務,通知的粒度爲服務實例所在的容器IP。
第二步:Gateway-SynchSpeed 接受到請求後,先校驗IP的可用性,而後通知Eureka Server。
第三步:Eureka Server 將 Producer 置爲失效狀態,並返回處理結果(Eureka 下線形式分爲兩種,一種是直接從服務註冊列表直接剔除,第二種是狀態下線,便是將 Producer 的狀態置爲OUT_OF_SERVICE
。 若是是以第一種形式下線,Spider平臺發出下線請求後,不能保證Producer進程馬上被kill,若是這期間 Producer 還有心跳同步到 Eureka Server,服務會從新註冊到 Eureka Server)。
第四步:Gateway-SynchSpeed 獲得上一步結果,若是結果爲成功,則執行下一步;反之,則中止。
第五步:Gateway-SynchSpeed 爲Eureka Client。Gateway-SynchSpeed 經過 IP 到本地服務註冊列表中獲得 Producer 的 Application-Name。
第六步:Gateway-SynchSpeed 經過 Application-Name 到網關核心庫中查詢全部與下線服務相關的 網關組名字
。
第七步:Gateway-SynchSpeed 經過 網關組名字
到本地服務列表中查找網關組下全部的服務地址 ipAddress(ip : port)。
第八步:Gateway-SynchSpeed 異步通知全部相關網關節點。
第九步:Gateway-Core 收到通知後,對 Producer 作狀態下線,同時記錄全部狀態下線成功的實例信息到緩存 DownServiceCache 中。
第十步:Gateway-Core 更新本地 Ribbon 服務列表。
Eureka 提供了一種安全保護機制。Eureka Client 從 Eureka Server 更新服務列表前,會校驗相關Hash值是否改變( Client 服務列表被修改,hash值會改變),若是改變,更新方式會從增量更新變成全量更新,(由《Eureka 緩存機制》可知這30s內 readOnlyCacheMap 和 readWriteCacheMap 的數據可能存在差別),若是Client端緩存列表被readOnlyCacheMap 覆蓋,最終會致使 Ribbon 端服務列表與 readWriteCacheMap 數據不一致。
針對 Eureka 這種機制,引入監聽器 EurekaEventListener 做爲補償機制,它會監聽 Eureka Client 全量拉取事件,對於緩存中未超過30s的服務,將其狀態從新設置成 OUT_OF_SERVICE
。
考慮到系統的安全性問題,若是被人惡意訪問,可能會使生產者在Eureka Server中無端下線,致使消費者沒法經過 Eureka Server 來發現生產者。
使用黑白名單作安全過濾,基本流程以下:
對 Gateway-Synchspeed 中設置白名單網段(IP網段)
在 Gateway-Synchspeed 加入過濾器,對下線請求方進行IP校驗,若是請求端IP在網段中,則放行;反之,過濾。
因爲 Gateway-SynchSpeed 和 Gateway-Core 是部署在 Docker 容器中,若是容器重啓,會致使日誌文件所有丟失。因此須要將 Gateway-SynchSpeed 和 Gateway-Core 中相關日誌寫入到 Elasticsearch ,最終由 Kibana 負責查詢 Elasticsearch 的數據並以可視化的方式展示。
Gateway-SynchSpeed 作狀態同步
EurekaEventListener 處理緩存數據
目前網關實現對服務下線的實時感知中,使用的 Zuul 和 Eureka 版本爲 Spring Cloud Zuul 1.3.6.RELEASE 、Spring Cloud Eureka 1.4.4.RELEASE。
目前網關實現的是對網關下游服務的實時感知,並且需知足如下條件:
網關服務下線實時感知是網關對業務方提供的一種可選的解決方案,在 spider 平臺中默認是沒有開啓此功能,是否開啓此功能由業務方根據自己系統要求決定,具體如何配置可參考 API網關接入指南 中 《網關實時感知在spider上配置文檔說明》。
做者:謝國輝
來源:宜信技術學院