螞蟻Service Mesh探索與思考(下):解決研發效能挑戰

導語:

上次跟大家分享了 螞蟻Service Mesh探索與思考(上):打造不一樣的基礎能力。在過去的一年多時間裏,螞蟻在 Service Mesh 上建設了大量能力,而這些基礎設施能力的快速演進正是得益於 Service Mesh 將業務和基礎設施的解耦。


Service Mesh 落地之後,我們曾設想過 Service Mesh 再向前探索可能會遇到的種種困難,包括資源利用率、性能損耗等等,但是未曾想到過去一年中最大的挑戰是研發效能。


研發能效的挑戰

當 Service Mesh 的優勢逐漸顯現,越來越多的能力希望下沉到 MOSN 中。而我們也逐漸發現 MOSN 在實際迭代過程中遇到的一些困難,其中比較突出的兩個難題:

1. 變更量大 :大量的功能希望進入 MOSN,因此每一個 MOSN 的版本發佈都是一次代碼量巨大的變更。這對質量保障和技術風險的挑戰都是很大的。

2. 集中式發佈 :以前由業務應用升級基礎組件 SDK 的方式,由各個業務應用主動發起升級的發佈,發佈時主要由該業務應用自己監控其系統穩定性。這種升級方式從覆蓋的空間和時間上來說都是分散的,便於灰度和發現問題。而 MOSN 的升級方式則是集中式的。即使按照萬分之一容器數量進行灰度,這個數字都是巨大的。這對質量保障和技術風險的挑戰也是很大的。
面對這些難題,每一個 MOSN 的版本在上線之前需要很長時間的測試,上線過程中需要很長時間的灰度。但是當最終發佈上線後,如果出現一個問題,則又會導致整個版本的回滾,長時間的測試和灰度付之一炬,又需從頭再來。在面對穩定性這個壓倒一切的要求時,退讓的就是 MOSN 的研發效能。即各個功能從開始開發到最終全集羣覆蓋的速度。這是在犧牲 Service Mesh 的核 心價值啊!這是我們所不能接受的。因此只有在質量保障和技術風險上突破掉這些挑戰,才能讓 Service Mesh 發揮出它真正的價值。
  • 質量保證

在 MOSN 研發流程中,質量保障作爲研發效能中的關鍵一環,重點需要解決的難題:

多模塊共建質量: 雲原生背景下,除去 Service Mesh 自身外,很多業務方的訴求也一併下沉至 MOSN,多個業務方的共建質量複雜度幾何倍的提升,如何保障共建方也持續高質量的輸出。
版本穩定性: MOSN 的每一次發佈,變更內容多、變更範圍廣,如何確保每個版本的穩定性,以及線上多個版本共存情況下,版本之間的兼容性。
效能提升: 在保障質量穩定性的前提下,如何提升版本測試的效能。

測試策略上,我們主要通過雲原生多模塊質量數據建模版本穩定性兩個維度解決上述問題。

  • 雲原生多模塊質量數據建模

  • 對於 MOSN 裏的每個模塊的功能,除了基礎的單元測試和集成測試保障手段外,我們期望通過錄制線上的真實流量,經過數據清洗和建模後,獲取 MOSN 中不同模塊的真實業務場景,作爲 MOSN 中多模塊測試場景的輸入;另外,MOSN 支持 MOCK 模式,對這些線上錄製的業務場景,在線下做自動化的回放驗證。

    多模塊數據採樣

    這裏採集的數據共包含:流量數據、業務特徵數據和內存配置數據。

    MOSN 使用 Golang 語言編寫,無法像 JAVA 一樣,通過 JVM 插樁的方式實現流量的錄製和回放。

    對於 Golang 語言的錄製回放工具,開源也有優秀的工具,如 tcpcopy 和 goreplay 等,這些工具主要是從程序外部,對生產的正式流量進行錄製,而這對於 MOSN 並不適用。

    如能力建設部分所述,螞蟻內部通信目標 100% 覆蓋鏈路加密,使用上述工具錄製的流量爲加密後的流量數據,線下回放時,會因爲證書問題導致回放失敗。因此,我們需要在 MOSN 內,建立一套流量錄製、業務特徵數據上報、內存配置數據上報的能力,我們稱之爲 Test Mesh 的能力。

    流量錄製: 錄製的是 TLS 解密後的二進制數據。
    數據上報: 提供統一的數據上報接口,供 MOSN 中不同的業務模塊上報各自的流量特徵數據,通過和錄製的流量做關聯,達到流量清洗和線上流量建模的目的。
    數據採樣: 對於持久化的數據(包括二進制數據、流量特徵數據、內存鏡像和靜態配置),通過配置中心控制採樣開關和採樣頻率,在開關開啓的情況下,根據採樣頻率開啓採樣窗口,每個採樣窗口內同一個業務類型採集一筆流量。
    熔斷保護: 爲了不影響主流程,流量錄製和數據上報均設計爲同步受理異步處理的模式,且支持根據 CPU, MEM 的水位自動熔斷的能力,水位的閾值支持動態調整。

    建模清洗

    數據同步:線上錄製的數據持久化到磁盤文件中,通過數據服務平臺將數據同步至離線 ODPS 表中。
    數據清洗:算法模塊包裝了數據清洗的原子能力(如:正則匹配、去重等),用戶通過不同模塊上報的流量特徵數據,指定清洗規則,由算法平臺定時做數據清洗,並將清洗後的數據同步至存儲平臺,構成不同業務模塊的業務場景基線。

    模型場景回放

    有了業務場景和二進制流量,我們構建了回放系統,並在 MOSN 內部支持了 MOCK 模式,支持線下回放驗證。
    MOCK 模式:線下回放時,MOSN 基於線上採樣的內存配置加載起來後,其與外圍的配置需要全部 MOCK 掉,確保內存不會被線下的 Registry、動態配置中心 等更新掉,保障回放結果的正確性。
    流量回放:回放系統提供回放任務觸發、任務編排、MOSN 以 MOCK 模式拉起、回放執行、結果展示等功能。
  • 版本穩定性

    持續集成

  • 我們在原有持續集成 pipeline 流水線的基礎上,提出了更高的要求:每個代碼 PR 合併後即達到可發佈的狀態。

    提交的每個 PR 均會觸發這樣一條流水線的運行,每個 PR 獨立構建測試環境,並在整個 pipeline 流程中集成了研發、測試活動,從而確保 PR 合併後即可達到發佈狀態。
    這裏僅簡單介紹了 pipeline 的流程,pipeline 中的每個 job 還在持續建設中。

    功能預演

    原先在 MOSN 的研發流程中,MOSN 版本交付後,逐步灰度升級生產的業務應用,這中間缺失了一環 MOSN 自身生產升級的灰度驗證能力。
    爲此,我們搭建了 MOSN 自身的預演應用,這些應用模擬線上業務應用的真實使用場景,且按照線上真實業務應用部署。MOSN 每個版本交付後,先對這些應用做升級驗證,確認無問題後再做業務應用的升級,從而實現 MOSN 自身的灰度發佈和版本升級的質量保障。
    對於這裏說的“真實使用場景”,其數據也是來源於 Test Mesh 錄製到的流量特徵數據,這些流量特徵數據經過清洗 建模後,構建了業務場景基線,預演應用參照業務場景基線達到對線上“真實使用場景”的全面覆蓋。
  • 技術風險

通常來說,減小升級頻率就會將穩定性的風險減小。畢竟代碼變更是導致故障的一大來源。但是這對 MOSN 來說是不可接受的,例如一年我們只做一次發佈升級,前面提到了 MOSN 的代碼變更量是較大的,可想而知一年堆積下來的代碼變更量是多麼巨大。加上集中式的發佈方式,這就好像是把一顆“代碼變更炸彈”在短時間內扔在了不小數量的容器上。對 MOSN 自身的這一大量代碼變更來說,要保證完全沒有問題有不小挑戰,容易導致我們無法成功完成這次全集羣升級。所以這不僅對穩定性是挑戰,對 MOSN 的研發效能也是挑戰。如何去解決這個問題呢,這裏我們解讀兩個對這方面的探索。一個是採取更低侵入高頻的發佈方式,我們反而利用更加高頻的發佈模式來將較大量的變更風險分散開來;另一個是對健康度的度量,這能讓我們對每個 MOSN 節點的健康情況都準確掌握,做到更加自動化的發佈和相應的技術風險決策。

  • 低侵入高頻發佈

  • MOSN 是以 sidecar 形態與業務容器共同部署在 Pod 內。由於 MOSN 依賴與應用的業務進程交互獲取應用的服務信息,與服務配置中心交互並建立連接。這些信息在 MOSN 的發佈過程中都需要重建。因此 MOSN 的發佈過程也要求應用容器同時做重啓,以保證應用的服務信息能完整的在 MOSN 重新被初始化。但由於應用的啓動速度通常較慢,這個方式也嚴重的降低了 MOSN 的發佈效率。

    在最初考慮這個問題時,我們做了一些熱升級的嘗試,但熱升級引入了多個 MOSN 容器的交互,大幅增加了運維複雜性,因此我們又探索了新的低侵入發佈模式,我們稱之爲溫升級——僅關閉一切流量,不通知應用業務進程,接近業務無感方式的發佈。

    溫升級整體的流程如下。

    流量管理與服務元數據的繼承
    我們 在原有持續集成 pipeline 流水線的基礎上,提出了更高的要求: 每個代碼 PR 合併後即達到可發佈的狀態。
    MOSN 接管了業務的所有進出流量,並直接與流量相關的中間件交互,因此 MOSN 具備從源頭關停流量的能力。當發佈開始後,MOSN 先從各中間件註銷自身,確保不再承接流量,之後 MOSN 容器退出銷燬,kubelet 使用新的 image 重建新的 MOSN 容器並啓動 MOSN。
    由於此時無法從應用業務進程獲取服務的元數據信息(業務進程不知道 MOSN 進行了更新),新啓動的 MOSN 只能從之前的 MOSN 繼承這部分信息:MOSN 會準實時的將所有的動態配置信息(含服務元數據)dump 到一個共享的掛載卷,當新的 MOSN 容器啓動時,也會掛載同一個卷,並在 MOSN 進程啓動時加載這些配置,從而最大程度繼承原來 MOSN 的狀態。
    由於依賴於舊版本動態配置信息的加載,MOSN 也做了相應的向下兼容,確保升級過程中的元數據都能正確加載。
    連接重建
    完成狀態繼承後,MOSN 將自身所在 Pod 重新發布到服務配置中心等中間件,並開啓與遠程建立多個主動或被動的連接。對於後端的服務連接來說,MOSN 的升級過程就是一次普通的連接中斷,通常的服務框架都能自動處理連接中斷並重試建立新的連接。
    高頻發佈
    當低侵入的發佈實現之後,更高頻的發佈也變得可能。我們基於溫升級的能力,建設了從研發迭代直通到生產的 nighly build 交付的 CI/CD 流程,讓新研發的功能代碼在風險可控的前提下能夠以最快的速度接觸到生產流量,縮短了反饋迴環,極大加快了新能力的落地。
  • 健康度度量

  • 當新版本的 MOSN 發佈後,如何快速知道 MOSN 運行得是否健康。除了傳統的監控方式外,我們讓 MOSN 將自己的健康度主動透出,並配套監控平臺,發佈平臺和巡檢系統做到第一時間發現問題,自動暫停發佈和回滾。

    靜態健康度

    MOSN 定義了標準的組件框架,MOSN 中的每個組件都需要實現健康狀態的相關接口將自己的健康狀態細緻地透出。例如:註冊中心客戶端會透出自己和服務端的連接狀態、心跳狀態,透出自己每一個訂閱和發佈結果等;配置中心客戶端會透出自己和服務端的連接狀態,透出自己對每一個配置的拉取結果等。這些組件的狀態和結果會作爲發佈後流量是否開啓的前置檢查項,如果有組件不健康則不會開啓流量。巡檢平臺也會在查看 MOSN 運行時的健康狀態,如果是不健康的狀態則會阻斷繼續發佈。

    動態健康度

    靜態健康度側重在以組件的視角去觀察各個組件自身運行情況的健康情況,動態健康度則是側重在以全站流量的視角去觀察各個 MOSN 節點的健康情況。以 RPC 爲例,每一筆調用其實都是 應用_A -> MOSN_A -> MOSN_B -> 應用_B 的模型,這個模型中可以從 6 個地方觀察到這筆調用的健康狀態:應用_A 的 Egress 視角,MOSN_A 的 Ingress 和 Egress 視角,MOSN_B 的 Ingress 和 Egress 視角,應用_B 的 Ingress 視角。每一個視角都可以做調用情況的統計,基於這些調用統計,最終可以聚合計算出每個 MOSN 節點的健康情況。
    如圖 應用_B 的 Egress 成功率和 MOSN_B 的 Ingress 成功率下跌,由此可判斷 MOSN_B 節點爲不健康狀態,而 MOSN_B 的 Egress 成功率未變,所以還能進一步判斷是 MOSN_B 的 Ingress 模塊可能出現了問題。如果此時 成功率_7 也出現下跌,而 成功率_8 和 應用_A -> MOSN_A -> MOSN_C 鏈路上的成功率都未發生改變,則可判斷是 MOSN_B 的 Egress 模塊出現了問題。
    實際上,我們的動態健康度的度量維度會更復雜一些,例如還會區分出該筆流量是在 MOSN 節點內部發生異常還是在發起調用之後發生異常,還會有 MOSN 的版本等信息,由此可以更加精確的定位到出現異常的 MOSN 節點,並追溯到它的發佈單及迭代等信息,幫助最終的自動化決策
  • 問題診斷

在質量保障和技術風險的強大保障下,每一次 MOSN 的升級已經達到了一個高水準的穩定性。但是 MOSN 升級的覆蓋範圍之大,場景之複雜,有的問題甚至可能在幾個月之後纔會暴露出來,如何再去發現這些漏網之魚的 corner case 呢。其中有一些問題較難定位,這些問題的特點是:發生隨機,過程時間短,難以抓到現場。一些偶發的 CPU 使用飈升、OOM 的問題對穩定性是大風險,我們需要有辦法把這些問題儘快定位出來,不能讓其一直潛伏到業務的關鍵時間點再爆發。
我們選取程序所佔用的 CPU、RSS 和 goroutine 數來作爲進程的運行時指標。分爲兩種情況:
  1. 如果這些指標在較短時間內發生較大波動,那麼認爲可能發生了瞬時抖動
  2. 如果這些指標到達非預期的閾值,那麼認爲可能發生了資源泄露或瞬時抖動
對上述三個指標,每經過 5s 採集一次,保存在相應的環形數組中。每次採集新一輪指標時,均與之前十個週期的數值平均(可以認爲是一種形式的 moving average)進行 diff,並判斷當前的值是否已到達預期外的閾值。
  1. 若 CPU 規則被觸發,自動啓動 Go 的 CPU Profile,並將文件保存在日誌目錄中
  2. 若 RSS 規則被觸發,自動將 Go 的 heap Profile 保存在日誌目錄中
  3. 若 Goroutine 規則被觸發,自動將 Go 的 goroutine Profile 保存左日誌目錄中
這些功能上線之後,我們只要根據監控系統推下來的報警 host 找到相應的目錄位置,並把 profile 下載到本地慢慢分析就可以了。
診斷功能上線之後幫我們定位出了多個之前難以發現的漏洞/代碼問題,我們將該功能沉澱爲一個開源 lib: holmes ,目前已開源在 MOSN 組織下。

總結及未來

在過去一年中,得益於 Service Mesh 的落地,我們的基礎設施得到前所未有的演進速度,並在性能,效能,穩定性和可用率等各方面幫助業務得到提升。
在向前探索的過程中,我們越發看清 Service Mesh 真正價值的體現不在於它建設了多少能力,而是體現在它自身將這些基礎設施能力大規模應用於業務的週期和穩定性。
由此我們發現 Service Mesh 目前最大的挑戰其實是它自身的研發效能,只有一個高效和穩定的 Service Mesh 才能持續不斷地將基礎設施能力賦予業務並得以演進。因此我們在質量保障,技術風險和問題診斷上也在不斷突破創新,最終使得 Service Mesh 的核心價值真正發揮了出來。
螞蟻的 Service Mesh 一直走在這個領域的最前沿,接下來我們又會向什麼方向探索呢。我們會持續將更多的能力下沉至 MOSN ,接管所有的進出流量,讓任意技術棧的應用只需要接入 MOSN 就能擁有完整的基礎設施能力;結合螞蟻豐富的實踐經驗與社區的力量制定出一套 API 作爲應用和控制面等同 Service Mesh 交互的標準,一起推進 Service Mesh 的發展;不斷結合業務挖掘出有價值的場景,通過 Service Mesh 的優勢爲業務帶來幫助;我們也會通過技術創新讓 MOSN 具備被集成的能力( https://github.com/mosn/mosn/issues/1559 ),使得 MOSN 和更多優秀高性能網關生態打通,進一步發揮 MOSN 沉澱的能力, 從而釋放 1 + 1 > 2 的技術紅利;另外會持續投入開源,MOSN 的核心能力一直是開源共建的方式,不斷吸取社區良好的輸入,並與螞蟻內部大規模場景下的實踐相碰撞,最終又將這些優秀的能力貢獻於社區。

本文分享自微信公衆號 - 瓜農老梁(gh_01130ae30a83)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

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