java分布式系統開關功能設計(服務升降級)


 ​問題一:在單個java系統中如何實現開關功能?

    ​    ​其實對於開關來說,對應Java中的類型,很好映射,就是一個boolean值,在需要做開關操作的地方,調用這個屬性,判斷狀態,然后走相應的邏輯即可。這個類是一個單例,保證全局唯一(代碼就不寫了,單例模式一般是學習設計模式中最開始接觸的呵呵)。

 

    ​    ​問題二:單個java系統中,如何實現開關值變更的操作呢?

    ​    ​在單機系統中,改變開關的狀態很簡單(留一個口子,外部可以改變屬性的值,例如改為true或者false),這時候,可以是頁面來維護開關,通過頁面的點擊類改變這個全局唯一的屬性,從而實現開關動作的觸發。

 

    ​    ​問題三:多個同構java系統,如何實現開關狀態的同步呢?

    ​    ​通過一和二的介紹,在單機情況下,開關的變更可以了,但是在多個同構(這里的同構,值得是部署的同一套代碼,邏輯完全相同,類似Master和Slaver的模式)系統中,如何保持一致呢?單例模式,開關屬性是被加載到本地緩存,就是說java一直持有的對象,在FullGC的時候回收不走的那種。這個時候,如果要保持各個系統中開關屬性狀態的一致,就需要從第三方外部系統中加載這個數據。

    ​    ​什么系統能充當第三方外部系統呢?可以是一個數據庫訪問系統,我們暫且稱之為MetaServer,開關的屬性防止在DB中,然后MetaServer提供頁面來修改數據,同時提供接口讀取開關的數據,在應用啟動的時候,通過MetaServer來讀取數據,加載到本地緩存中。這時候就有個問題,就是我通過MetaServer的頁面改變了值,各個應用如何知道我改變了屬性呢?這個時候就需要通過一些辦法(辦法很多,可以是消息系統,可以是zookeeper,可以是頁面觸發)來清理一下開關屬性的緩存,讓緩存重新加載一下,從而實現最新的狀態獲取。

    ​    ​總體思路就是:metaServer維護開關數據--應用讀取DB中的數據到本地緩存--DB中數據變更--觸發開關屬性緩存重新加載。

    ​    ​這個是不是有點復雜,有沒有更加簡單的辦法?當然有了,之前淘寶開源了一個系統diamond(持久化配置管理系統,http://code.taobao.org/p/diamond/wiki/index/),其實可以理解為“配置信息的偽推送服務”,例如我變更了一個開關的屬性,不再需要做清理緩存的事情,diamond幫你做掉了(原理很簡單,例如系統A訂閱了在diamond中的開關信息,這時候A會啟動一個線程,每隔一段時間來輪循diamond的服務端,看看開關屬性的數據有沒有變更,如果有變更,在diamond服務端來加載最新的數據)。

    ​    ​總體思路是:在diamond中維護配置信息--系統訂閱開關屬性--系統輪循配置是否有變更,有變更直接就變掉了。

 

    ​    ​問題四:開關設計的幾個坑

    ​    ​有時候,我們為了方便,沒有借助問題三種的MetaServer或者diamond的方式,就是留了一個HTTP的接口來觸發修改開關(多台機器的話,可以寫批量腳本),這時候其實需要我們在apache或者nginx中,把這個URL的訪問禁止掉,防止惡意用戶在外部拼湊鏈接來進行開關的變動,這時候只能在服務器上通過linux的curl來觸發操作了。

    ​    ​還有一個,就是如果通過HTTP的形式來修改開關的屬性,有個是需要注意的,就是開關的執行要冪等操作,這樣方便操作,避免出現集群中數據不一致的狀態(就是執行開,開關就是開,不能第一次執行是開,第二次執行是關)。

 

    ​    ​問題五:開關組合情況下怎么搞?

    ​    ​上面的幾種情況,僅僅是執行單個開關,應該比較簡單。但是我同時又A、B、C三個開關,在不同的業務場景下,可能需要關閉A和B開關,在另外一個場景下,可能需要關閉A和C開關,這時候認為操作有可能會有遺漏或者疏忽,怎么搞呢?在單獨屬性開關的基礎上做封裝,例如A和B上面增加一層屬性,暫且叫“AB”,修改AB的值,對應的系統修改A和B的值,這樣就避免人肉記住一些組合。

 

    ​    ​問題六:如何實現自動升降級?

    ​    ​上面的情況,都是在提起可以預知的情況下,我們做一些人為的操作,這個能不能自動化?當然可以,就是這一小節討論的自動升降級。

    ​    ​舉例子,現在東京和作的外部物流公司有多家,會調用它們的系統或者物流節點的狀態,這個時候,物流公司系統是不穩定的,如果掛了或者響應時間慢了,對於自身的系統會影響比較大,比較理想的辦法是,在物流公司系統出現問題的時候,這塊邏輯自動降級處理,然后等物流公司系統好了之后,再把這部分邏輯自動升級,整個過程沒有人為參與,自動保持系統穩定性。這里說一下總體思路:

    ​    ​第一步:搞一個計數器,記錄接口,暫定A的調用成功次數、失敗次數以及響應時間;

    ​    ​第二步:將這些信息放入隊列中,同時設置閥值(例如RT超過5秒就降級,1秒就升級)以及閥值觸發改動的開關;

    ​    ​第三部:異步啟動一個線程,掃描隊列,達到我們的條件,就觸發做變更(有個問題,就是加入業務降級了,這時候就沒有調用量,也就沒有了自動升級的條件了,怎么搞呢?這時候業務降級,並不是完全100%的停掉,可以預留一部分流量繼續調用A,把A調用的信息放入隊列中,根據這些信息,就能實現升級了);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM