怎麼做配置下發

目錄

 

配置下發

少量用戶

大量用戶

複雜場景

開拓思維


配置下發

我們做開發,無論是做中間件還是業務都會面臨一個問題,我們的客戶端或者APP發版本後,需要運行中動態加載一些配置,比如負載均衡、服務發現等,這些配置需要從服務端來獲取,並且在配置變更後,客戶端可以及時或非及時的得到最新的配置。

把問題抽象化,即我們客戶端如何獲取最新的配置,也就是配置下發的問題。

 

少量用戶

最開始,配置下發可能會比較簡單,無論是採用TCP長連接或者是HTTP短連接等等,我們客戶端定時的與服務端進行通信,每次從服務端拉取最新的配置,客戶端進行本地更新即可。

這是最基本也是最簡單的模式,但是問題也很明顯,如果配置文件較大,並且更新較少的時候,每次服務端發送給客戶端的配置大部分都是無用流量。

我們可以在客戶端請求配置文件時,攜帶文件的MD5,服務端在只有MD5不相同時,即文件發生變化時,再把配置文件下發給客戶端;沒有變化時,只需要告知客戶端無變化狀態即可。

這樣,我們就節省了大量無效的流量。

 

大量用戶

我們的客戶端規模越來越大,當有一天已經到了十萬、百萬級的時候,我們再看這種方案是否還可行。

雖然,在配置沒有變化時,我們服務端返回的ack信息都是一個簡單的狀態,但是當配置文件發生變化時,如果配置文件很大,很快網絡帶寬資源就會成爲瓶頸。

如果可以知道配置都有哪些發生變化,每次只返回給客戶端發生變化的配置,這就極大程度上節約了網絡帶寬資源。

現在的問題點就在於如何知道哪些配置發生了變化。

最容易想到的,就是服務端在配置文件發生變化時,記錄下變化的配置,在客戶端拉取配置時,只需要返回變化的配置文件即可。

並且正常情況下,客戶端都會在很短的時間內獲取最新的配置,如果有異常客戶端,在一段時間內還沒有更新到最新的配置,我們可以對這少部分的異常客戶端進行全配置更新。

如此,我們只需要在服務端爲配置文件標記一個順序遞增的版本號,在有配置發生變化時,記錄發生變化的配置,並對版本號加一。

  • 當客戶端來請求配置文件時,攜帶本地配置文件的版本號,當版本號相同時,說明無變化,依舊返回無變化狀態即可;
  • 當客戶端配置文件版本號比服務端小1時,服務端才返回變化的內容;
  • 其餘情況都認爲客戶端更新配置異常,返回全量數據即可。
  • 客戶端收到配置後更新本地版本號。

 

複雜場景

以上,我們基於一般正常的情況來設計的方案,如果客戶端場景很複雜,經常有長時間不啓動或者不聯網的客戶端,他的配置文件就會落後很多版本。或者如果配置文件更新比較頻繁,頻繁程度超過了客戶端請求配置的間隔。

那麼我們上面的方案又退化回了服務端每次返回全量配置了。既然我們無法相信不確定的客戶端,我們就需要在服務端來做一些手腳了。

我們記錄每次配置的變化,在客戶端來請求配置時,根據兩者版本號的差異,獲取之間配置文件的所有變化,彙總後發送給客戶端,那麼就解決了這個問題。

當每次配置發生變化時,服務端依舊記錄變化的配置,並對版本號加一。並且將版本號與配置文件變化映射成一組關係保存起來,在內存或者保存到文件、數據庫、redis都可以。當客戶端來請求配置文件時,依舊攜帶本地版本號,利用本地版本號與服務端最新的版本號做比對。

  • 版本號相同時,說明配置未發生變化,返回無變化狀態。
  • 當客戶端版本號大於服務端版本號時,說明客戶端配置異常,返回全量數據。
  • 當客戶端版本號小於服務端版本號時,根據兩者的版本號差異,獲取之間的所有變化,彙總後返回給客戶端。
  • 客戶端收到數據後更新本地版本號。

當然,我們同樣可以設置一個閾值,即服務端只會保存最近的M個版本的配置變化,用來防止服務端保存數據無限膨脹。並且變化較多時,彙總的差異可能已經與全量數據幾乎相同。

當客戶端與服務端的版本差異大於M時,依舊返回全量數據即可。

 

開拓思維

我們聯想一下,服務端的這種配置管理與GIT的版本管理非常相似,所以有時候我們最怕的不是技術不夠,而是思維不夠開闊。

那麼我們再進一步開拓一下思維,這種記錄配置文件變化,是不是又與Redis的AOF很相似。如果,我們可以設計一種統一的記錄配置變化的元語,那麼我們是不是也可以實現Redis中AOF的的重寫?

如果我們可以實現AOF的重寫,是不是就省去了大量的合併版本差異的重複操作。

那麼我們可以對配置進行k\v化,應該說所有的配置都可以拆分爲一系列的k\v組合。我們再定義一組操作元語,就用我們經常自嘲的CRUD來定義,我們取其中的CUD:

C:新增

U:更新

D:刪除

這三種操作就幾乎囊括了配置的所有變化。那麼我們的配置變化就可以記錄爲:

C:K:V

U:K:OLD:NEW

D:K

那麼我們服務端,就可以定期的對配置變化進行重寫合併。例如:

  • 對同一個K的U操作,可以只保留最後一次
  • 對同一個K的D操作前的所有CUD,可以只保留最後的D操作
  • 對同一個K的先C後U操作,可以合併爲C操作,V爲最後一次U的NEW值

等等,這裏只是舉個簡單的例子。這樣,一方面減少了服務端對配置變化的存儲數量,一方面也減少了每次客戶端請求配置時,服務端大量的重複合併差異的冗餘操作。

是不是還能再繼續擴展下思維?我想應該是可以的,而我就暫時說到這裏。

比如我們返回給客戶端的不一定是變化的配置,也可以是這些操作的元語,是不是又可以減少一部分的數據包大小。

生硬的結束~困了

個人原創公衆號,期待關注:

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章