dubbo藍綠
目前做devops項目,去年提供了藍綠發布功能,因此分享下,首先介紹下幾種常見的部署方式,最后介紹下藍綠發布的實現
1.常見部署方案介紹
1.1.藍綠發布
藍綠部署,是指同時運行兩個版本的應用,藍綠部署的時候,並不停止掉老版本,而是直接部署一套新版本,等新版本運行起來后,再將流量切換到新版本上。但
是藍綠部署要求在升級過程中,同時運行兩套程序,對硬件的要求就是日常所需的二倍,比如日常運行時,需要10台服務器支撐業務,那么使用藍綠部署,你就需
要購置二十台服務器。藍綠發布本質就是使用硬件冗余的方式,實現發布過程中的0 downtime,在新版本有問題后,可以通過一鍵回滾到舊版本。
1.2.A/B Testing
A/B 測試跟藍綠部署完全是兩碼事。
A/B 測試是用來測試應用功能表現的方法,例如可用性、受歡迎程度、可見性等等。 A/B 測試通常用在應用的前端上,不過當然需要后端來支持。
A/B 測試與藍綠部署的區別在於, A/B 測試目的在於通過科學的實驗設計、采樣樣本代表性、流量分割與小流量測試等方式來獲得具有代表性的實驗結論,並確信
該結論在推廣到全部流量可信;藍綠部署的目的是安全穩定地發布新版本應用,並在必要時回滾。
A/B 測試和藍綠部署可以同時使用。
1.3.灰度發布
灰度發布是在原有版本可用的情況下,同時部署一個新版本應用作為“金絲雀”(金絲雀對瓦斯極敏感,礦井工人攜帶金絲雀,以便及時發發現危險),測試新版本
的性能和表現,以保障整體系統穩定的情況下,盡早發現、調整問題。
灰度發布可以保證整體系統的穩定,在初始灰度的時候就可以發現、調整問題,以保證其影響度。
1.4.滾動發布
滾動發布能夠解決掉藍綠部署時對硬件要求增倍的問題。
所謂滾動升級,就是在升級過程中,並不一下子啟動所有新版本,是先啟動一台新版本,再停止一台老版本,然后再啟動一台新版本,再停止一台老版本,直到升級完成,這樣的話,如果日常需要10台服務器,那么升級過程中也就只需要11台就行了。
但是滾動升級有一個問題,在開始滾動升級后,流量會直接流向已經啟動起來的新版本,但是這個時候,新版本是不一定可用的,比如需要進一步的測試才能確認。那么在滾動升級期間,整個系統就處於非常不穩定的狀態,如果發現了問題,也比較難以確定是新版本還是老版本造成的問題。
為了解決這個問題,我們需要為滾動升級實現流量控制能力。
目前容器部署通常使用滾動發布,舊版本依然提供服務,直至新版本服務完全啟動。
1.5.小結
灰度發布主要在於業務方,可以評估一下不同版本客戶的反饋效果來決定是否發布。
藍綠發布和滾動發布的側重點就是發布。
2.dubbo藍綠發布的實現
dubbo藍綠可以通過兩種方式實現,使用tag路由或者dubbo的路由規則,下面分別介紹下優缺點
2.1.tag標簽路由實現藍綠
dubbo的標簽路由使用很方便,啟動的服務直接加上-Ddubbo.provider.tag=blue/green,這樣就實現了藍綠的流量隔離。
使用藍綠之前的流量請求結構
使用藍綠后
dubbo服務使用tag標簽進行流量隔離,具體要訪問藍綠哪個服務,由web服務控制。
使用tag標簽路由有個問題,就是調用別人的服務需要和自己的tag相同,或者對方服務不存在tag。如果其它被調用服務也使用了tag,那么就會找不到服務。因此使用tag路由的,還需要准備套沒有tag的服務便於調別人服務。這也是個麻煩點,實際上,功能並沒有路由規則強大,但是勝在簡單。
2.2.路由規則實現藍綠
比如我們的服務架構如下圖
用戶通過網關(dubbo泛化)來訪問我們的dubbo服務,我們的代碼都是寫在dubbo服務內。現在想通過藍綠,實現下面的效果
其中dubbo服務藍綠對應線上的新舊版本。
做法是:對於藍綠應用啟動時候分別追加自定義啟動參數-Ddubbo.provider.parameters.blueGreenTag=blue/green,那么線上就存在了兩套服務,分別是藍綠服務。那么如何進行藍綠切換呢?比如我們的流量接入都是由網關控制,網關使用的dubbo泛化,網關提供個藍綠切換接口,在服務發布后,通過devops平台點擊藍綠切換,用戶就可以選擇由藍切換到綠,由綠切換到藍。具體的實現就是dubbo的路由規則了。即在這個dubbo應用下的的所有服務的routers節點創建/修改一天route地址,而由於網關會監聽對應服務的routers節點,因此zk通知dubbo consumer端(即網關)refreshinvoker,從而網關就會調用對應的藍/綠服務。
這里有兩個疑問:
1.自定義的啟動參數-Ddubbo.provider.parameters.blueGreenTag=blue/green是如何加載的?
2.為什么我通過devops平台點擊切藍/切綠按鈕后,網關就只會調用藍/綠服務?
解答:
1.自定義的啟動參數-Ddubbo.provider.parameters.blueGreenTag=blue/green,在dubbo啟動過程中,會自動保存到ProviderConfig.parameters集合(因為會自動把dubbo.provider開頭參數綁定到ProviderConfig的對應屬性上),其中key就是blueGreenTag,value就是blue/green,這樣在服務暴露時候,在doExportUrlsFor1Protocol操作內appendParameters(map, provider, Constants.DEFAULT_KEY);
,就會把ProviderConfig.parameters集合參數保存到map上,從而注冊到zk上的provider url上就會攜帶上自定義的參數,例子如下圖
dubbo://192.168.5.1:20880/org.pangu.api.ProductService
anyhost=true
application=pangu-service-provider
bean.name=ServiceBean:org.pangu.api.ProductService
default.blueGreenTag=green
default.tps=1000
default.tps.interval=2000
dubbo=2.0.2
generic=false
interface=org.pangu.api.ProductService
methods=findProduct,selectProduct
pid=10876
side=provider
timestamp=1627397851153
可以看到自定義的啟動參數default.blueGreenTag=green,注意:默認會增加default開頭
這里要注意的是AbstractMethodConfig.parameters,是dubbo提供的用於自定義參數,會追加注冊的url上。
比如我線上是藍服務,現在發布新版本,發布到綠服務上,綠服務啟動成功后,但是實際網關調用的還是藍服務,因此就需要進行流量切換了
2.通過devops平台點擊切藍/切綠按鈕后,會去調用網關的接口,網關根據上送的應用名(dubbo應用名),查找到當前應用下所有的服務(網關會維護所有的dubbo服務名),從而修改每個服務下的router協議,修改zk上router url的例子如下
/dubbo/${interface}/routers/route://0.0.0.0/${interface}?category=routers&dynamic=false&enabled=true&force=false&name=blueGreenRule_${ruleSuffix}&priority=0&router=condition&rule=consumer.methods=*+=>+provider.default.blueGreenTag=${tag}&runtime=false&type=javascript
//ruleSuffix是藍綠標識+group+version,比如blue_zzzGroup_1.0.0
//tag表示blue/green
從這個具體的url可見,router url的rule是consumer.methods=*+=>+provider.default.blueGreenTag=${tag}
,表示是消費端所有的方法,都去請求服務端攜帶藍/綠標識的服務。
實際上是router url被修改后,zk通知網關(dubbo consumer),網關從而refeshInvoker,然后根據ConditionRouter進行路由篩選provider端default.blueGreenTag=green的服務(在toMethodInvokers內),從而最終緩存到RegistryDirectory的服務都是green服務。
說完了dubbo服務的流量切換,還有外部流量的接入,即web服務的流量切換,這里使用的是k8s提供的Ingress,扮演着 “智能路由” 或者集群入口的角色,本質就是個nginx,使用lua腳本進行web流量切換。這個后續再進行深入了解。