復雜系統(tǒng)如何在不停機升級同時保持穩(wěn)定?你必須考慮以下幾個點
背景
在互聯(lián)網(wǎng)行業(yè),線上服務的升級更新可謂家常便飯。據(jù)統(tǒng)計,在過去的一個季度中閑魚工程師們執(zhí)行了千余次發(fā)布,總計更新的代碼數(shù)量超過百萬行。
這些發(fā)布中,有一些可能只更新了幾行代碼,而有一些可能執(zhí)行了整個集群的遷移升級。而無論這些變更的影響面有多大,我們都必須保證線上服務的可用性,用戶無感知。本文將以閑魚搜索服務的遷移升級為例,向大家介紹其背后的技術(shù)方案。
閑魚搜索服務基本架構(gòu)
閑魚的底層搜索服務由查詢規(guī)劃服務 Search Planner、查詢理解服務 Query Planner、打分排序服務 Rank Service 以及搜索引擎 Heaven Ask 3 所組成。它們之間的相互調(diào)用關(guān)系如下圖所示:
可以看到,整個搜索服務是由多個相互獨立的微服務所構(gòu)成的。不同的微服務之間相互隔離,通過預先向外暴露的接口提供服務。所有的微服務最終通過 Search Planner 收口,對外提供統(tǒng)一、完整的搜索能力。
在底層搜索服務之上,還有業(yè)務邏輯層和接入網(wǎng)關(guān)層,具體架構(gòu)在此不再贅述。用戶的搜索請求先通過網(wǎng)關(guān)層轉(zhuǎn)發(fā)給邏輯層處理,再向底層搜索服務發(fā)起搜索請求。這條請求鏈上包含數(shù)十個集群,調(diào)用深度達到兩位數(shù),整個過程中提供服務的服務器數(shù)量可能有成百上千。
對于這樣一個復雜的系統(tǒng),升級過程顯然無法一蹴而就。好消息是各個微服務之間合理的解耦合給升級工作帶來了很大的便利,有效避免牽一發(fā)動全身而導致無從下手,使我們可以分門別類地處理升級問題。
注1:Search Planner 是一個基于函數(shù)式、服務化、可視化、并行化開發(fā)框架所構(gòu)建的搜索服務網(wǎng)關(guān)層。
注2:Query Planner 的主要作用是理解用戶輸入,然后對搜索詞進行算法優(yōu)化。最終獲得更好的搜索召回結(jié)果。
注3:Rank Service 是實時打分排序服務,它的作用是根據(jù)多維度的特征對搜素引擎召回的海選結(jié)果進行算法打分。分數(shù)越高的商品就越有機會出現(xiàn)在搜索結(jié)果的前列。
注4:Heaven Ask 3 (問天3)是阿里巴巴研發(fā)的一款穩(wěn)定高效、功能強大的搜索引擎。為阿里集團包括淘寶、天貓在內(nèi)的核心業(yè)務提供搜索服務支持。
保持兼容
開始升級之前,我們首先需要確認被升級的服務是否保持了向前與向后兼容性。保持兼容不僅減少了工作量,也減少了升級所導致的故障風險。
為了盡量避免升級導致的不兼容,我們可以總結(jié)一些開發(fā)原則:
遠程過程調(diào)用(RPC)需要能夠忽略未知參數(shù),并且允許缺失參數(shù)。
如果需要刪除已有參數(shù),需要與所有依賴方確認??梢韵葘?shù)標記為 Deprecated 而不是直接移除。
使用參數(shù)時,區(qū)分缺省值和缺失值。
如果接口無法保持兼容,則創(chuàng)建新接口代替舊接口。不要破壞舊接口的兼容性。
在升級時,先升級那些沒有外部依賴的服務。等到被依賴方升級完畢之后,再去升級依賴方。確定了每一個服務的升級順序之后,我們再根據(jù)服務的實際情況確定升級方案。
無狀態(tài)服務升級
正式進入升級流程,我們首先關(guān)注搜索鏈路中的被設(shè)計成無狀態(tài)服務的部分,例如用于處理業(yè)務邏輯的 Java 微服務、用于處理查詢邏輯的 Search Planner 等。它們的共同特點是,每個請求處理完畢之后,關(guān)于該次請求的資源即被釋放。不同的請求之間沒有相互依賴和時序要求。同一個無狀態(tài)服務內(nèi)不同的機器節(jié)點是完全等價的。
無狀態(tài)服務的特點使得它們很容易通過水平擴展來動態(tài)擴縮容。因此在保證兼容的前提下,它們的升級流程相對通用并且簡單:
根據(jù)服務最小可用度決定分批數(shù)。
選取一批待更新的容器,停止服務。
批量升級容器、更新鏡像。
等待這一批容器全部恢復服務后,繼續(xù)更新下一批容器。
一般來說我們可以通過把狀態(tài)存儲在消息隊列、緩存、數(shù)據(jù)庫或者其它外部中間件中來達成服務的無狀態(tài)。把服務設(shè)計成無狀態(tài)的好處顯而易見:升級時不需要分配額外的機器資源,升級速度快,變更代價小,因而可以支持頻繁的迭代更新。但是,這種設(shè)計也給狀態(tài)訪問和更新帶來了額外的開銷,在某些性能敏感的場合可能是不適用的。
有狀態(tài)服務升級
我們繼續(xù)關(guān)注有狀態(tài)的部分。有狀態(tài)服務升級的麻煩之處在于,狀態(tài)的存儲、恢復、轉(zhuǎn)移往往由服務根據(jù)實際情況單獨設(shè)計(或者根本沒有設(shè)計),因而升級較為困難。我們可以簡單列舉一些相對通用的有狀態(tài)服務升級可選方案。
接入層網(wǎng)關(guān)提供熱更新的能力(例如 Nginx),把狀態(tài)的保持隔離在接入層內(nèi)部。適合需要長時間保持狀態(tài)的場景。
漸進更新,新請求逐步切換到新服務上處理,舊服務處理完存量請求后銷毀。適合短時間保持狀態(tài)的場景(例如游戲服務、實時音視頻通訊服務)。
創(chuàng)建全新的服務副本,通過數(shù)據(jù)雙寫保持新舊服務狀態(tài)一致,逐步用新服務取代舊服務。
在閑魚搜索的架構(gòu)中,搜索引擎本身提供的雖然是無狀態(tài)服務,但是引擎內(nèi)部保存了用于處理索引分區(qū),增量進度的各種狀態(tài)。最終使用的升級方案如下:
使用新版本鏡像創(chuàng)建一個完全獨立的新引擎。
新舊引擎全量數(shù)據(jù)同步。
增量數(shù)據(jù)同時向新舊引擎發(fā)送。
新引擎上線,逐步擴大承接流量的比例。
舊引擎不再承接流量后下線。
和無狀態(tài)服務的升級相比,這種方式不僅額外使用了一倍的機器資源,而且每次升級都需要做一次復雜而繁瑣的服務配置。如果服務本身不是無狀態(tài)的,還需要自行編碼實現(xiàn)切流邏輯,保證同一個用戶的請求能夠落到同一個集群上。整體升級成本較為昂貴,只適合更新頻率非常低的服務。如果服務的更新頻率較高,則應該根據(jù)服務的實際情況設(shè)計實現(xiàn)升級成本更低的方案。
服務發(fā)現(xiàn)
在升級過程中,服務發(fā)現(xiàn)機制承擔著重要作用。它為我們提供了以下功能:
保證分布式一致性
服務優(yōu)雅上下線
負載均衡
流量調(diào)控與請求降級
同機房優(yōu)先調(diào)度
跨機房容災調(diào)度
服務發(fā)現(xiàn)是流量調(diào)控的總閥門。一個成熟穩(wěn)定的服務發(fā)現(xiàn)機制不僅可以有效避免發(fā)布導致的請求成功率抖動,也為發(fā)生異常時快速回滾止血提供了保證。
風險防控
對搜索鏈路的每一個集群按照依賴順序進行服務升級、掛載、切流無疑是高危操作,稍有不慎就可能引起線上故障。因此,我們按照阿里巴巴安全生產(chǎn)三板斧原則對升級流程進行了梳理:
可監(jiān)控:重要鏈路的重要指標均提前保證監(jiān)控覆蓋。例如請求總量,請求成功率,請求響應時長等等。確保重大問題可以通過監(jiān)控指標及時發(fā)現(xiàn)。
可灰度:任何變更都不允許未經(jīng)灰度直接全量發(fā)布到線上。對于無狀態(tài)服務,我們一般通過調(diào)整服務發(fā)現(xiàn)中的權(quán)重或者調(diào)整機器比例來完成灰度放量。對于部分不能隨機灰度的情形,我們設(shè)計了按用戶分批放量的機制。
可回滾:變更系統(tǒng)提供了通用的一鍵回滾能力,但并非是最快的方式。在很多情況下,我們在執(zhí)行變更前就做好了把待更新的機器或集群在服務發(fā)現(xiàn)上重新掛載或移除的準備,從問題發(fā)現(xiàn)到恢復的時間基本是秒級的。
總結(jié)
綜上所述,復雜系統(tǒng)不停機升級的原則和流程可以概括如下:
服務間解耦與隔離,確保單次升級的范圍和影響可控。
根據(jù)兼容性和依賴關(guān)系決定服務的升級順序。
根據(jù)服務是否無狀態(tài)決定升級方式。
提前準備好監(jiān)控和回滾方案,灰度升級。
閑魚搜索服務升級的整個執(zhí)行過程經(jīng)歷了兩個月的時間。這其中我們既保證了用戶無感知,線上服務穩(wěn)定運行,也保證了與我們合作開發(fā)的算法團隊以及其他工程團隊的正常開發(fā)不受影響。
在實際執(zhí)行的過程中,我們還遇到了很多細節(jié)上的問題。例如創(chuàng)建新服務時未能提前合理預估預算需求,導致升級過程中不斷挪借預算,拆東墻補西墻。又比如異地多活部署帶來的延遲問題迫使服務保持單元化,給升級過程中的流量調(diào)控工作帶來了很多挑戰(zhàn)。這些暴露的問題也為我們繼續(xù)完善架構(gòu)和方案提供了指引。
希望本次的分享能夠給大家?guī)硪恍椭蛦l(fā)。
特別推薦一個分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長按關(guān)注一下:
長按訂閱更多精彩▼
如有收獲,點個在看,誠摯感謝
免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!