螞蟻Service Mesh探索與思考(上):打造不一樣的基礎能力

導語:

在《螞蟻Service Mesh大規模落地實踐與展望》一文中,我們系統介紹了螞蟻建設Service Mesh的歷程。不過,建設過程當中仍然有許多問題值得探討和思考。有了Service Mesh之後,建設基礎能力和之前有什麼不一樣的地方?接下來請看研發團隊的分享。


能力建設

得益於 Service Mesh 將業務和基礎設施解耦,在過去一年中我們的基礎設施能力得到了飛快的發展。大量能力大規模落地螞蟻,例如鏈路加密、可信身份認證、服務鑑權、自適應限流、集羣限流、精細化引流、服務自愈等。這裏先對四個能力進行解讀,其它能力後續再有文章講述。
  • 1. 鏈路加密

爲了達到一個更高的安全水位,我們預期在螞蟻內部所有的通信 100% 加密覆蓋,這就是鏈路加密。

  • 設計

鏈路加密落地最大的挑戰就是加密對業務不能造成影響,包括幾個問題:
  1. 必須簡化大規模場景下的運維複雜度問題,需要具備可灰度、可回滾的能力。
  2. 灰度運行期間,明文和加密切換不能對業務請求造成影響,需要進行熱切換。
  3. 開啓加密以後,對性能的影響必須控制在可接受的範圍內。
基於這些需求,完成了鏈路加密的架構設計,主要思路包括:
  1. 通過統一的管控面控制服務端應用的配置,基於動態服務發佈與訂閱機制,在服務端支持加密能力以後,客戶端自動進行加密的切換,運維人員只需要控制服務端配置節奏完成灰度;在灰度運行期間,服務端同一個端口需要同時支持明文和加密的能力。
  2. 相比於明文通信,基於 TLS 加密的通信主要消耗在連接建立的握手期間,服務端和客戶端採用長連接的方式,減少連接的建立,以減少開啓加密對性能的影響。
  3. 客戶端在感知到服務端明文和加密狀態變化以後,需要在不同的長連接之間進行穩定的切換,後文會詳細介紹。
完整的一個加密開啓流程如圖所示,首先運維人員在管控面選擇需要開啓加密的應用,通過 XDS 完成配置下發。 MOSN 在收到配置以後,會基於 SDS 機制獲取到證書和私鑰在內存中,證書和私鑰由統一的 Secret 進行管理,應用側不持久化保存。 收到證書和私鑰以後,會向註冊中心發佈本機已經支持了加密,註冊中心會向所有訂閱的客戶端進行推送,客戶端收到推送以後,與服務端的通信切換到加密狀態。
  • 加密狀態熱切換:連接淘汰機制

我們的加密通信是基於 TLS 進行的實現,一個連接在建立好並且開始傳輸數據以後,連接上的數據是 TLS 加密的還是明文的就已經固定了,不存在將一個明文通信的連接變成 TLS 加密連接的情況。基於 TLS 這個機制,通信從明文切換到加密時,一定是需要新建一個連接,並且成功完成 TLS 握手。
爲了做到在連接切換期間業務請求不受影響,MOSN 實現了一個連接淘汰機制,用於連接加密狀態的熱切換。
每一個請求在 MOSN 中經過了路由和負載均衡以後,會選擇到一個後端地址,基於這個地址從連接池中選擇對應的長連接轉發請求,在引入了加密切換以後,每次選擇到連接以後,都需要判斷當前預期的加密狀態和連接的加密狀態是否匹配,如果不匹配,則會創建新的連接進行加密狀態的切換,並且使用新連接將連接池中的舊連接代替,這樣就可以確保後續的請求都使用狀態匹配的連接。對於被替換的舊連接,我們需要進行淘汰,但是這個淘汰不是簡單的斷開連接,因爲舊連接上可能還有正在處理的請求,如果直接將連接斷開就會導致請求有損,這是不能接受的。
那麼是如何淘汰舊連接的呢?這裏就要講到 MOSN 的長連接保持機制了。爲了避免因爲異常斷網等導致連接“假死”的情況,在連接空閒時,會主動發起心跳請求,確保連接處於活躍狀態,而如果服務端一段時間內都沒有收到心跳,則會主動將連接斷開。連接淘汰就是利用這個機制,對於準備淘汰的連接,我們將停止該連接的心跳發送,當連接上的請求處理結束後,這個連接上就不再會有任何數據的傳輸,經過一段時間後,服務端就會主動將這個連接斷開,此時連接斷開是安全的,不會影響任何請求。
  • 優化
對應用無感知開啓加密,除了指開啓過程中不需要重啓、請求無損等,還包括在開啓以後 的資源消耗、RT 影響也需要是無感知的。 在實際落地應用過程中,由於我們都是使用長連接,TLS 握手帶來的建連消耗只佔用了很少一部分,在長連接通信過程中的對稱加密消耗經過實際測試幾乎可以忽略不計,看上去鏈路加密對性能的指標沒有什麼問題。
但是在實際大規模落地以後,我們發現部分應用開啓了加密以後,內存佔用有顯著的上漲,經過排查,定位到屬於 GolangTLS 標準庫實現問題( MOSN 是使用 Golang 編寫的),我們自行優化以後,也向 Golang 官方提了 PR 回饋社區,目前該 PR 已經被 Golang 官方所接受,預計在 go1.16 中發佈,具體實現可以見  crypto/tls: pool Conn's outBuf to reduce memory cost of idle connections
  • 2. 自適應限流

流量管理本身就是 Mesh 架構最爲核心的功能之一,我們在 MOSN 中實現了多種策略的限流能力,包括單機 QPS 限流、集羣限流、熱點限流、接口熔斷、自適應限流等,其中自適應限流是一大亮點。
限流是每個技術同學都不陌生的名詞,同時也是很多不同角色的同學頭疼的事情。對於業務同學而言逐個接口做容量評估和壓測迴歸費時費心,有限的精力只能投入到重點的接口保障上,難免會漏配一些小流量接口的限流;而負責質量和穩定性保障的同學經常在故障覆盤時看到各種漏配限流、錯配限流、壓測故障、線程阻塞等造成的各種故障......
我們希望即使在系統漏配錯配限流的情況下,在系統資源嚴重不足時 MOSN 能夠精準的找到導致系統資源不足的罪魁禍首,並實時根據系統水位自動調節異常流量。這就是自適應限流想要實現的效果。
  •  技術原理

能用一句話說清楚你們的技術原理嗎?
類 PID 控制流量閉環自適應調節
樸素的解釋就是,觸發限流後一邊觀察系統整體水位,一邊秒級按比例調節流量的策略,用一張圖來解釋具體的原理:
  1. 系統資源檢測 秒級檢測系統資源佔用情況,如果連續超過閾值 N 秒則觸發基線計算,同時開始拒絕壓測流量進入。
  2. 線計算 將當前所有的接口統計數據遍歷一遍,通過一系列算法找出資源消耗大戶,再把這些大戶裏明顯上漲的流量找出來,把他們當前的資源佔用做個快照存入基線數據中。
  3. 基線調節器 將上一步驟存入的基線數據根據實際情況進行調整,根據系統資源檢測的結果秒級的調整基線值,若系統水位超過閾值則按比例下調基線值,否則按比例恢復基線值,如此反覆。
  4. 限流決策 根據上述步驟生產的基線數據決策是否限流。
自適應限流已在全站線上應用中大規模啓用,成功防範了多起業務故障。爲新春紅包壓測和線上業務保駕護航。
  • 技術原理

相較於傳統的限流組件,M OSN  中的自適應限流具備很多優勢,MOSN 架構天然的流量劫持讓應用無需逐個接入 SDK,也無需爲特定語言開發不同版本的限流組件,同時給業務同學降低了配置的難度,也爲業務實現了兜底保護。在研發效能和研發成本上都取得了明顯的 收益。

MOSN  自適應限流
傳統 QPS 限流組件
規則數量
每個應用只需要 配一個
每個接口都需要配置一個
觸發條件
按系統整體水位
按接口調用量
限流值
動態實時計算
固定值
生效點
在 MOSN 中攔截
在應用的限流組件攔截
接入與升級成本
已 Mesh 化的應用自帶,無成本
應用接入 SDK ,接入和升級需做發佈
  • 3. 精細化引流

隨着業務發展,應用面對越來越多的場景和問題,而我們發現很多應用在各自的業務場景和解決問題的過程中對流量的調度能力有了越來越強的訴求。MOSN 的精細化引流正是爲滿足這樣的訴求而生,它將應用的流量調度以原子能力的方式透出,然後控制面和各個平臺對這些原子能力進行場景化的編排使用。基於該能力,目前已支撐灰度發佈,容災,機房建設和容量壓測等諸多場景。
  • 單應用引流

單應用切流是指在單元化的架構下,利用 MOSN 對流量的代理和調度能力,將應用粒度的流量從當前部署單元引流到另外的部署單元。

如圖應用 A 和應用 B 是上下游關係,它們對等部署在單元 1 和單元 2 兩個部署單元。應用 B 將自己的地址註冊到註冊中心。應用 A 通過註冊中心發現應用 B 的地址,然後發起 RPC 調用,調用收斂在單元內。單元 2 內應用 B 的 MOSN 根據切流規則將來自上游的流量轉發到單元 1 的應用 B。單應用引流的方式可用於多種場景,如:
  1. 灰度發佈: 當應用 B 需要做新的迭代發佈,可以先將流量都 100% 切到單元 1,然後完成單元 2 集羣的發佈,再將單元 1 的流量逐量回切回來,中間有問題隨時回切。
  2. 容災: 當應用 B 的其中一個單元因爲代碼配置變更或其它原因導致長時間不可用時,可將流量都切到其它部署單元。
  3. 機房新建: 可將已有部署單元的應用的流量用該方式引流到新機房內的部署單元做驗證。而當新的部署單元都完整引流後,這個時候如果出現個別應用有問題,也不必將整個部署單元的流量回切,利用單應用切流將出問題應用的流量切回原部署單元即可。
另外 MOSN 的單應用切流還支持接口級別的切流,支持部署單元之間的多到一,一到多,多到多的方式。這樣靈活的切流方式,爲業務帶來了很大的想象空間,相信未來會有越來越多有價值的解決案例在此基礎上生長出來。
  • 引流壓測

隨着業務發展,應用不斷髮布,在多次迭代之後,應用的性能水位離之前的基線已經走遠多少了呢。如果沒有一個好的性能管理方式,日常機器集羣不斷擴容,增加成本。每次大促臨近,大家開始梳理變更,設計壓測方案,然後反覆壓測發現性能問題,再迭代發佈解決問題,時間存在風險,問題的積累不可控。引流壓測利用 MOSN 的精細化引流能力,將線上集羣流量引流到單機進行性能壓測。每天自動迴歸,常態化地繪製出應用的性能基線。

  • 業務鏈路隔離

當你給別人轉賬,這筆流量其實會經過一條具有 n 個應用的鏈路的處理。微服務的架構帶來了諸多好處,也會帶來如穩定性的一些挑戰。如這筆轉賬流量所涉及到鏈路中的 n 個應用,任意一個應用出現了不可用,就會導致這筆支付失敗。是否可以讓這些應用都識別出如支付這樣重要的鏈路,爲其提供高可用的保證。基於 MOSN 的引流能力我們做到了業務鏈路隔離的方案。

如圖有 A,B,C 三個應用,A->B->C 的鏈路承擔了一筆轉賬的完整處理,另外還有應用 X,Y,Z 等應用和用戶會向 A,B 應用發起調用。A,B,C 應用被分爲了 GROUP_1 和 GROUP_2 兩個分組,各自分組的機器在向註冊中心註冊自己地址時會將該分組信息帶上,上游在發起調用時因此而能區分出下游不同分組的集羣。再根據流量的標識而選擇將流量路由到哪一個集羣。所以平臺下發給 MOSN 的規則如下:
Match: type = transfer 
Action: Group = Group_2
請求頭中含有 transfer 的流量始終路由到 GROUP_2 分組,其它流量都路由到 GROUP_1 分組。這樣就可以將重要流量隔離於其它流量,避免被其它流量導致的限流熔斷等影響。在機器資源,發佈策略,灰度策略上會有更優先的考慮。當重要分組的集羣出現不可用時,還可將流量切換到其它分組集羣以容災。
  • 4. 服務自愈

傳統的服務自愈,需要依賴於外部的探針( probe )。這個探針可以是監控系統,可以是 k8s liveness probe。實現的方式主要是主動的服務探活,和被動的日誌採集分析。這些方式都存在時延與準確性的問題。主動的探測可能由於網絡或探測器負載等原因誤判,導致業務被誤自愈;被動的日誌分析,則需要長鏈路的日誌採集分析系統,時間以分鐘級計。
回到根源,自愈本質是要解決服務可用性的問題,而 MOSN 承接了所有的服務流量。因此在 MOSN 內部的自愈邏輯可以說是放在了離問題最近的地方。
簡單來說,我們在 MOSN 內部實現了一個異常計數器,來統計篩選並剔除異常的節點,同時上報給自愈中心,對涉及的節點進行進一步自愈動作。
首先我們在 MOSN 內部對於每個服務的異常請求做了統計計數。當統計視角可以區分出有明顯問題的遠端節點時,可以暫時的將該節點放入本機的調用黑名單中,避免問題持續。依賴於調用請求的頻率,統計的時間窗口可以從亞分鐘級到秒級。對於高頻的重要服務,單機問題的待續時間也被限制在了秒級,實現了服務的秒級自愈。
被黑名單的節點還需要進一步的處理。當節點被放入黑名單的同時,它的信息也會上報到自愈中心,並開始經歷數分鐘的冷卻時間,等待問題的進一步確認。自愈中心基於上報的黑名單節點再做二次聚合,並可以結合被動監控和主動探測等方式,在分鐘級的時間內使用重啓或下線等手段完成恢復動作。最終自愈中心確認爲沒有問題的節點,也會在冷卻時間後恢復服務。


Service Mesh的價值

以上只是例舉的幾個能力建設,實際上還有許多能力和落地場景這裏就不再一一展開。Service Mesh 在螞蟻落地之後,我們的基礎組件能力得到了飛速的發展。這得益於 Service Mesh 將業務和基礎設施解耦之後所帶來的紅利。
例如上文中講到的“業務鏈路隔離”,其實在很早之前我們有這個方案,可是受制於“上游系統難以推動升級”而一直未落地。在螞蟻的應用規模之下,絕大部分系統的上游數量都是巨大的,技術棧是多樣的,基礎組件版本是參差不齊的。
再例如“自適應限流”和“服務自愈”,這兩項技術存在一定的複雜性,它在有效性和穩定性上都存在一定的挑戰。需要在足夠多的真實場景下不斷去驗證,去試錯和迭代。而在 Mesh 之前的時代,全集羣的基礎組件升級一年不過一兩次。一個新能力沒有把握好一次機會也許就得再等一年。
而今天當我們擁有 MOSN 之後,它具備在不打擾業務的情況下將一個基礎能力快速覆蓋到全集羣的能力。這些基礎能力在未有 MOSN 的時候其實也能實現,但是在現實中卻因其落地時打擾業務,推進困難,迭代緩慢,版本碎片化嚴重等各種原因而無法真正實現。所以 Service Mesh 的價值得以體現。今年應用系統因基礎設施升級而發佈的次數大大減少,而我們的技術設施卻得到了前所未有的演進速度。


小結

在過去的一年多時間裏,螞蟻在 Service Mesh 上建設了大量能力,這些能力在性能,效能,安全,穩定性和可用率等多個方面爲業務帶來了幫助,也爲基礎設施帶來了快速的演進。 而這些最終正是得益於 Service Mesh 將業務和基礎設施的解耦。
在 Service Mesh 落地之後,我們曾設想過 Service Mesh 再向前探索可能會遇到的種種困難,包括資源利用率,性能損耗等等,但是未曾想到其中最先到來也是過去一年中最大的挑戰竟然是它。這裏先留個懸念,待下期文章進行分享。

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

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