PS:源碼已上傳Github, 歡迎指教。https://github.com/shileishmily/spring-cloud-x.git
什么是灰度發布呢?
要想了解這個問題就要先明白什么是灰度。灰度從字面意思理解就是存在於黑與白之間的一個平滑過渡的區域,所以說對於互聯網產品來說,上線和未上線就是黑與白之分,而實現未上線功能平穩過渡的一種方式就叫做灰度發布。
上一節講了Apollo作為配置中心的基本使用,但其更為強大的地方在於可以和Zuul+Eureka無縫集成,實現灰度發布。
本篇主要演示應用新版本發布后,我們只希望指定的用戶路由到我們的新版本服務器,其他用戶仍然訪問我們的老版本,如下圖:
圖中會使用Zuul,Apollo,Eeureka,這在之前我們已經講過,大家可以看看之前的文章。本篇除了要對spring-cloud-gateway模塊進行改造,還要新建兩個模塊x-demo-springcloud-gray-provider,x-demo-springcloud-gray-consumer對灰度進行測試使用。服務提供者和消費者在我們之前的pay-service,order-service,user-service基礎上進行改造也可以,為了讓代碼看的更清晰,我們選擇新建兩個模塊演示。
1、請求首先到達Zuul(GrayFilter),此時Zuul攔截器從請求頭中取出token,解析出對應的userId。
2、Zuul網關從Apollo配置中心拉取灰度用戶列表(GrayUserConfig),然后根據灰度用戶策略判斷該用戶是否是灰度用戶。若是,則給該請求添加請求頭及線程變量添加信息version=xxx;若不是,則不做任何處理放行
3、在Zuul攔截器執行完畢后,Zuul在進行轉發請求時會通過負載均衡器Ribbon。
4、負載均衡Ribbon被重寫。當請求到達時候,Ribbon會取出Zuul存入線程變量值version。與此同時,Ribbon還會取出所有緩存的服務列表(定期從eureka刷新獲取最新列表)及其該服務的metadata-map信息。然后取出服務metadata-map的version信息與線程變量version進行判斷對比,若值一直則選擇該服務作為返回。若所有服務列表的version信息與之不匹配,則返回null,此時Ribbon選取不到對應的服務則會報錯!
5、當服務為非灰度服務,即沒有version信息時,此時Ribbon會收集所有非灰度服務列表,然后利用Ribbon默認的規則從這些非灰度服務列表中返回一個服務。
6、Zuul通過Ribbon將請求轉發到consumer服務后,可能還會通過fegin或resttemplate調用其他服務,如provider服務。但是無論是通過fegin還是resttemplate,他們最后在選取服務轉發的時候都會通過Ribbon。
7、那么在通過fegin或resttemplate調用另外一個服務的時候需要設置一個攔截器,將請求頭version=xxx給帶上,然后存入線程變量。
8、在經過fegin或resttemplate 的攔截器后最后會到Ribbon,Ribbon會從線程變量里面取出version信息。然后重復步驟(4)和(5)
參考:https://segmentfault.com/a/1190000017412946