拉模式主要是在客戶端按照訂閱關係發起主動拉取過程。客戶端在首次訂閱能夠進行一次相關服務 ID 的服務列表查詢,並拉取到本地緩存,後續經過長輪詢按期進行服務端服務 ID 的版本變動檢測,若是有新版本變動則及時拉取更新本地緩存達到和服務端一致。這種模式在服務端能夠不進行訂閱關係的存儲,只須要存儲和更新服務發佈數據。由客戶端主動發起的數據獲取過程,對於客戶端實現較重,須要主動獲取和定時輪訓,服務端只須要關注服務註冊信息的變動和健康狀況及時更新內存。這個過程因爲存在輪訓週期,對於時效性要求不高的狀況比較適用。
**SOFARegistry 服務發現模式採用的是推拉結合方式。**客戶端訂閱信息發佈到服務端時能夠進行一次地址列表查詢,獲取到全量數據,而且把對應的服務 ID 版本信息存儲在 Session 回話層,後續若是服務端發佈數據變動,經過服務 ID 版本變動通知回話層 Session,Session 由於存儲客戶端訂閱關係,瞭解哪些客戶端須要這個服務信息,再根據版本號大小決定是否須要推送給這個版本較舊的訂閱者,客戶端也經過版本比較肯定是否更新本次推送的結果覆蓋內存。此外,爲了不某次變動通知獲取失敗,按期還會進行版本號差別比較,按期去拉取版本低的訂閱者所需的數據進行推送保證數據最終一致。
主動獲取:服務訂閱信息註冊到服務端時,須要查詢全部的服務提供方地址,而且須要將查詢結果推送到客戶端。這個主動查詢而且拉取的過程,推送端是一個固定的客戶端訂閱方,不涉及服務 ID 版本信息斷定,直接獲取列表進行推送便可,主要發生在訂閱方應用剛啓動時刻,這個時期可能沒有服務發佈方發佈數據,會查詢到空列表給客戶端,這個過程基本上相似一個同步過程,體現爲客戶端一次查詢結果的同步返回。
版本變動:爲了肯定服務發佈數據的變動,咱們對於一個服務不只定義了服務 ID,還對一個服務 ID 定義了對應的版本信息。服務發佈數據變動主動通知到 Session 時,Session 對服務 ID 版本變動比較,高版本覆蓋低版本數據,而後進行推送。此次推送是比較大面積的推送,由於對於這個服務 ID 感興趣的全部客戶端訂閱方都須要推送,而且須要按照不一樣訂閱維度和不一樣類型的客戶端進行數據組裝,進行推送。這個過程數據量較大,而且須要全部訂閱方都推送成功才能更新當前存儲服務 ID 版本,須要版本更新確認,因爲性能要求必須併發執行而且異步肯定推送成功。
按期輪訓:由於有了服務 ID 的版本號,Session 能夠按期發起版本號比較,若是Session 存儲的的服務 ID 版本號高於dataServer存儲的 ,Session再次拉取新版本數據進行推送,這樣避免了某次變動通知沒有通知到全部訂閱方的狀況。
服務推送性能優化
服務訂閱方的數量決定了數據推送一次的數量,對於一臺 Session 機器來講目前咱們存儲 sub 數量達到60w+,若是服務發佈方頻繁變動,對於每次變動推送量是巨大的,故咱們對整個推送的過程進行優化處理:
即便對服務變動進行了合併延遲處理,可是推送任務產生也是巨大的,因此對於瞬間產生的這麼大的任務量進行隊列緩衝處理是必須的。目前進行全部推送任務會根據服務 ID、推送方 IP 和推送方信息組成惟一任務 ID 進行任務入隊處理。隊列當中若是是相同的服務變動產生推送任務,則進行任務覆蓋,執行最後一次版本變動的任務。此外任務執行進行分批次處理,批次大小能夠配置,每一個批次處理完成再獲取任務批次進行處理。
補償措施:對於推送失敗以前也說有定時任務進行輪訓服務 ID 版本,服務 ID 的版本在全部推送方都接受到這個版本變動推送才進行更新,若是有一個訂閱方推送失敗,就不更新版本。後續持續檢查版本再啓動任務,對沒有推送成功的訂閱方反覆執行推送,直到推送成功或者訂閱方不存在,這個過程相似於無限重試的過程。
數據處理分階段
註冊中心數據的來源主要來自於兩個方向,一個是大量應用客戶端新鏈接上來而且發佈和訂閱數據並存儲在註冊中心的階段,另一個是以前這些發佈的服務數據必須按照訂閱方的需求推送出去的階段。這兩個階段數據量都很是巨大,都在首次部署註冊中心後發生,若是同時對服務器進行衝擊網絡和 CPU 都會成爲瓶頸,故咱們經過運維模式進行了兩個階段數據的分離處理:
關閉推送開關:咱們在全部註冊中心啓動初期進行了推送開關關閉的處理,這樣在服務註冊中心新啓動或者新發布初期,由於客戶端有本地緩存,在推送關閉的狀況下,註冊中心的啓動只從客戶端新註冊數據,沒有推送新的內容給客戶端,作到對現有運行系統最小影響。而且,因爲推送關閉,數據只處理新增的內容這樣對網絡和 CPU 壓力減小。