朵曉東,花名奕杉,螞蟻金服高級技術專家。專一企業雲計算技術及產品,螞蟻金融雲 PaaS 創始團隊核心成員,Antstack 網絡產品負責人。開源愛好者,Apache Kylin 創始團隊核心成員;SOFAMesh 創始團隊核心成員,SOFAMosn 項目負責人。git
本文根據曉東在 GIAC 上海站的演講內容整理,完整的分享 PPT 獲取方式見文章底部。github
你們好,我是螞蟻金服系統部的高級技術專家奕杉,今天分享的內容是:《螞蟻金服在 ServiceMesh 推動落地過程當中對新型網絡代理的思考和實踐》算法
主要的分享順序:後端
背景概述緩存
架構設計及功能特性安全
技術案例性能優化
總結展望網絡
ServiceMesh 做爲雲原生之上的服務網格技術在今年引發了業界的普遍關注,首先咱們來看一下目前 ServiceMesh 數據平面的一些方案。架構
最爲你們熟知的是老牌七層代理 Nginx 和 ISTIO 原生的數據平面 Envoy。Nginx 早已在國內外普遍使用,近兩年積極探索 K8S、ServiceMesh 微服務場景,並推出了與 ISTIO 集成的微服務解決方案,試圖擴展其場景邊界,拿下新的領域,從單純的7層流量代理到雲原生時代的智能數據平面轉型。但目前看 「NgMesh」研發不夠活躍,已知的使用方也很少。Envoy 做爲 Google 和 Lyft聯合開發的 ISTIO 原生數據平面產品,近兩年藉助 ServiceMesh 微服務場景快速打開了市場,並在一些互聯網公司推廣使用,同時引入了一批開發者進行 API 網關等功能網關的開發,發展勢頭很是好。負載均衡
其次 LINKERD 是基於 Rust 的一種高性能數據平面,但其發展空間受到了 Envoy 擠壓,業界使用的公司也比較有限。
螞蟻金服基於自身訴求自研了基於 Golang 的數據平面 SOFAMosn(後簡稱MOSN),並在螞蟻、UC 等公司落地使用。
同時對業界開源,提供了一種新的數據平面產品選擇。
此外國內的華爲、新浪等公司都基於自身場景提出了數據平面方案並前後進行了開源,數據平面競爭已經從獨霸業界的基於 Nginx 二開方案逐步轉變爲目前的多樣化產品同場競技的局面。
爲何衆多大廠紛紛投入研發數據平面呢?
我我的認爲新生技術棧、雲原生、微服務快速發展等契機對數據平面提出了場景多樣化、功能服務化、雲原生親和等多重挑戰。
以往從未像如今這樣對數據平面提出過如此多的要求:
數據平面須要執行部署運維中的流量切換;
須要提供雲親和的細粒度流量調度功能;
須要提供微服務親和的服務發現、路由組網特性;
須要以雲原生的方式感知資源;
須要支撐服務粒度、高度自定義的壓測、故障測試、線上灰度流量管理;
須要提供鏈路級、服務級的安全隔離保護,須要支持多種語言、多種協議的轉換分發能力;
須要能享受系統層面、硬件層面的紅利;
須要爲複雜的運維架構(如螞蟻的 LDC 等)提供可擴展的流量調撥能力等等;
固然根據每一個公司的業務場景可能還有其餘的因素。 最後,如何要將這些能力都匯聚在統一的數據平面產品上,彌合南北向、東西向數據平面因爲技術棧、團隊等差別帶來的鴻溝,變成了另外一個更爲複雜的問題。這裏所提到的問題中任何一點擴展開來均可以是一個豐富獨立的 Topic,受限於篇幅本次分享只能介紹咱們在解決這些問題中的一小部分思考和實踐。
首先,螞蟻已經將基於 ISTIO 的 ServiceMesh 方案 "SOFAMesh" 開源,在控制面咱們選擇克隆 ISTIO 官方版本並研發符合螞蟻需求的控制面,在數據面咱們選擇使用 Golang 研發數據平面 MOSN,目前已經支持了微服務場景所需的大量經常使用功能。
這裏我根據 ISTIO 的 Task 文檔總結了目前 SOFAMesh 支持的一些能力,如:透明攔截適配,細粒度的流控,故障注入,雙向鏈路加密等。對於一些暫時存疑的功能,如 Mixer Check 等,暫時沒有支持。目前 SOFAMesh 已在 UC 生產環境落地使用,知足了 Sidecar、Ingress、Egress 多種場景的使用需求。在這裏附上 SOFAMesh,SOFAMosn 的 Github 地址,也歡迎你們使用交流。 SOFAMesh:github.com/alipay/sofa… SOFAMosn:github.com/alipay/sofa…
再來看看螞蟻內部,因爲目前螞蟻生產環境還沒有大量鋪開K8S,而且已經存在一套完善的管控技術體系,加上目前ISTIO 的性能和穩定性還不知足大規模微服務場景等緣由,咱們暫時沒有選擇直接升級到 ISTIO,而是經過優先落地Sidecar 的方式來贏得 ServiceMesh 解決方案帶來的紅利。在螞蟻內部,MOSN 接管了SOFABoot 應用,代理了服務發現、路由/負載均衡、通訊等工做,構成了微服務網格,經過自有的中間件及管控平面進行微服務的管理、治理。同時,咱們積極的推動 MOSN 與 SOFA中間件,網絡接入層,安全防禦及監控體系的整合,以提供更統一更強大的數據平面。
接下來我將介紹 MOSN 支持多協議的方案。
爲了在內部快速落地試錯,咱們首先支持了內部使用最普遍的 SOFARPC 協議,並對其進行了深度優化。隨後咱們根據 UC Mesh 化推動遇到的廣泛問題提出了 XProtocol 方案,以在不解包的場景下提供路由能力。最後咱們深度改造了三方 HTTP/1.1 實現及官方 HTTP/2.0 實現。到目前爲止,MOSN 已提供了多種協議的支持。同時 MOSN 提供了兩種自定義協議的能力支持使用者經過擴展的方式自定義協議實現,知足須要解包、不須要解包的協議擴展需求。
除協議以外,性能是你們比較關心的另外一個問題。爲了提供知足生產要求的7層轉發性能,咱們在 IO、協議、內存、協程、網絡處理等方面進行了優化,從目前經過 SOFARPC 通訊應用的上線狀況來看能夠知足生產使用要求,在案例分析中我將展現一些性能數據,後續咱們也將繼續推動性能優化,以達到更好的性能。
在安全能力上,SOFAMesh 支持 mTLS,並在螞蟻內部集成螞蟻內部的 KMS 完成了 mTLS 落地,同時 RBAC 功能在研發中,此外WAF、流量鏡像能功能也在規劃中。
在螞蟻內部基於 MOSN 的網關產品正在研發中,將會在穩定驗證後開源。網關場景相對於 Sidecar 場景有一些特性需求,好比說通常會 Hold 住大量長連接,好比說會根據請求內容動態選擇後端應用,因爲網關可能代理了不一樣的後端應用,就會須要動態選擇後端協議。此外還有一些網關類的通用能力需求,如簽名,受權,限流等。
爲了能基於開源版建設螞蟻內部的 Sidecar 及網關產品,咱們充分考慮了開源版 MOSN 的擴展性,在路由、後端管理、TLS、網絡、流處理等各方面提供了擴展性支持。對於其餘使用 MOSN 的場景,也能夠經過相似的方式來知足自身業務定製需求。
爲了更清晰的展現 MOSN 功能特性,這裏將 MOSN 0.4.0 的功能特性經過表格的方式展現出來。能夠說0.4.0版本已經初步具有了生產所需的大部分功能點,支持雲原生場景下的多協議、路由&LB、後端管理、TLS、遙感監測、XDS對接等功能,並充分優化了性能,目前已經在螞蟻、UC生產環境進行了驗證。同時在螞蟻內部咱們經過擴展的方式支持了灰度路由、 LDC 路由、彈性路由,支持了配置中心等定製需求。後續咱們會繼續完善功能點,若是有發現未支持的功能能夠在 Github 給咱們提 Issue,或者直接加入咱們 commit code。因爲MOSN在擴展性上提供了比較好的能力支持,在特定的場景均可以經過擴展的方式來知足需求。
在介紹了架構、功能特性之後,我將介紹一些落地過程當中的技術案例。
首先咱們來看在螞蟻在非 K8S 場景下將 MOSN 做爲 Sidecar 接入應用的姿式。 在咱們推動落地初期,須要接入MOSN 的 SOA 應用尚未經過原生 K8S 的方式運行起來,服務發現是基於典型的服務發現中間件來作,也沒有直接使用 ISTIO 來落地。在這種狀況下,咱們經過擴展開源版 MOSN 支持服務發現,將 MOSN 做爲服務代理,由其完成服務 Pub/Sub,並代理服務完成 RPC 通訊。這裏有幾個要點,首先因爲內核限制咱們沒有第一時間使用Iptables 攔截請求,而是經過升級 SOFA 的方式來支持應用切換訪問地址,這裏須要應用方升級 SOFA 依賴,但不須要改業務代碼。
其次,咱們經過擴展開源版服務發現實現的方式支持從螞蟻配置中心獲取後端服務列表。在路由生成上,MOSN 基於完善的服務間依賴關係生成服務路由,因爲 SOFA 應用在編碼階段已明肯定義了服務依賴並在服務啓動時由 MOSN 代理完成 Pub/Sub,MOSN 感知所需的服務依賴關係,並動態生成了出向/入向路由。若是你的使用場景服務之間沒有明確的依賴關係,則須要擴展路由機制支持基於徹底請求內容的動態路由機制。其次,SOFA 服務尋址基於明確的 id:version信息,因此這樣的服務發現、路由方案同時也適用於相似的 SOA 服務,同時也能夠支持標準微服務尋址。這樣的擴展方式能夠實現基於服務發現中間件的非 K8S 的 Sidecar 注入,來享受 Mesh 思路落地的便利。
除了經過以上方式支持 SOA 化服務外,SOFAMesh 標準方案提供了一種基於 DNS 的尋址方案,以在不修改應用的狀況下支持標準微服務尋址。 首先經過 DNS 將服務名轉化爲 IP,同時在 MOSN 路由的 Virtual Host 中配置服務IP,以及與後端的匹配關係。Client 請求被 Iptables 攔截並轉發給 MOSN,MOSN 在處理請求時經過 Tcp Option 的 Original Destination 項拿到目標 IP,並做爲 Host 與 Virtual Host 匹配尋址到 Cluster 並作後端 LB及轉發。這樣在不進行微服務化改造的狀況下就能夠進行服務名完成尋址通訊了。這裏更多細節能夠參考敖小劍老師寫的XProtocol完整方案。
接下來咱們一塊兒分析另外一個在生產環境很是有用的特性,無損平滑升級。 大部分7層流量代理,包括 Nginx、Envoy等,在升級過程當中一般會讓老進程靜默等待一段時間後再退出、或等待時機由新進程控制退出,經過這種方式來保證老進程再也不處理到請求。這種方式對於 HTTP/1.x 短連接是比較有用的,但對於 HTTP/1.1長連接、RPC 長連接最終不得不經過暴力斷鏈的方式讓 Client 重連、重試,對業務是有必定影響的。凡會形成業務抖動通常都會形成業務方緊張,這會致使新功能升級推進困難。針對這個問題,MOSN 提出了本身的解決方案,在升級過程當中無損遷移存量連接,目前支持 HTTP/1.一、無狀態 RPC、TLS,後續將基於 Goaway 幀支持 HTTP/2.0。下面咱們來看看MOSN 是怎麼實現這樣能力的。
這裏我把典型場景抽象成 Client 請求處理和 Server 回覆處理兩部分,咱們先來看看 Client 請求處理。在升級階段,同時存在新老兩個 MOSN 進程,此時可能存在 Client 正在訪問老進程的狀況,此時老進程會經過 Domian Socket 將 TCP1 的 FD 及連接狀態數據傳遞給新進程,由新進程建立 TCP3 連接並將數據發送到後端 Server 並接收 Server 響應,新進程在收到響應後再也不轉發給老進程,直接轉發給 Client 完成本次請求。此後老進程退出 Read流程, 再也不接受該 TCP1 鏈接上的數據,同時新進程開始 Read 流程,接受該 TCP1 鏈接上的數據,完成 Reload 過程。
再來看看第二種狀況,在第一步連接遷移完成後仍然可能出現 Server 經過TCP2 將殘留響應發送到老進程的狀況,此時老進程會經過 Domian Socket 將請求數據傳遞給新進程,由新進程回覆到 Client。這樣就避免了兩個 MOSN進程同時寫到 Client 形成亂序的問題。延伸一下,將來基於這樣的思考能夠與容器 fork 結合提供容器、Pod 層面的無損遷移方案。
在遷移過程當中咱們發現,對於無狀態的 HTTP/1.1 長連接,RPC 長連接遷移較爲簡單,但對於有多回合握手的 TLS遷移則比較麻煩,這裏主要涉及到 TLS 的狀態數據遷移,如加密祕鑰,Seq 序列,讀緩存數據,Cipher 類型等狀態數據都須要作特殊的處理以保證遷移過程不會破壞握手過程。此外,MOSN 還支持對請求連接作明、密文檢測,來保證上游能夠灰度的開啓鏈路加密。
最後我將介紹一下咱們在性能優化方面的一些實踐。數據來源於 2018年8月份的 0.2.1 開源版。 先介紹一下在 Sidecar 模式下的性能數據,測試場景是一個典型的服務間通訊場景,服務A 經過 MOSN 訪問服務B。這裏選用的機型是螞蟻內部的測試機器。咱們測試的場景包括了 SOFARPC、HTTP/1.一、HTTP/2.0三種協議,測試的工具分別是螞蟻內部的壓測平臺、ab、h2load,其中 HTTP/2.0 壓測 5 條連接的場景,而且是 H2C,無 TLS 加密。數據場景是 1K 的請求、響應。
咱們來看一下測試結果,能夠看到 SOFARPC 性能遠好於其餘兩個協議。須要說明的是,HTTP/1.1 在 0.2.1 版本中直接使用了開源的 FastHTTP,MOSN 沒有接管 IO 處理,協議解析等工做,未作任何優化;HTTP/2.0 直接使用了官方實現,MOSN 沒有接管 IO 處理,協議解析等工做,未作任何優化。
在 SOFARPC 的優化上咱們從 IO,協議到上層處理作了很多優化,這裏簡單介紹一些優化經驗。首先分享一個踩過的坑,在基於 Golang Connection API 編寫讀數據代碼時,一個經常使用的方式是經過 SetReadDeadline 來設置讀超時,咱們發如今讀超時很短的狀況下,在2.6.2 內核會比 4.13.0 內核性能降低 30%,而經過綁核能夠解決此問題。此外,有不少有用的手段能夠用來優化性能,好比說讀合併減小協議處理次數,writev 減小系統調用寫的次數能夠有效提高總體吞吐量。咱們經過對比 Golang 和 OS 的 perf 數據發現 Golang 系統調用耗時比 OS 系統調用耗時要多(緣由還須要進一步明確),減小 Golang 系統調度老是有效的優化手段。在內存優化方案,首先能夠儘可能減小內存入堆,對於 100K 如下的內存入棧比入堆更快,而且不會影響 GC,對於不得不入堆的內存,能夠經過有效的內存回收複用減小內存建立,減小 GC 壓力。其次,在可控的範圍內池化協議能夠減小 Golang runtime 調度,並減小爲了 Golang 爲了保證連續棧而調用 morestack 形成的開銷。對於單核的場景,須要關注協程數量及協程使用率,避免協程飢餓的狀況。對於 perf 發現的熱點,須要有針對性的進行優化。
接下來看看網關的場景,Client 經過 MOSN 訪問 Server,測試條件與單核相似,不過沒有限制 MOSN 的 P,也沒有綁核。
從實驗結果上看,SOFARPC,HTTP/1.1 的結果基本在預期內,但 HTTP/2.0 性能遠低於預期。
咱們看到 Golang 官方的 HTTP/2.0 實如今多核場景下性能不佳,在 0.4.0 中對官方 HTTP/2.0 進行了性能優化,咱們將在 0.4.0 正式發佈後更新性能數據。在多核場景下咱們仍然選擇了單進程模型,根據鏈接數、負載等變化能夠壓到 4-8 核。咱們也嘗試了多進程綁核+reuse port 的方案,多核吞吐量高於單進程 15% 以上,但從容器的適配性,進程模型簡單等角度考慮咱們仍然選擇了單進程模型。在多核場景下須要特別關注全局鎖的性能和 IO 的優化,這也是官方 Golang HTTP/2.0 實現性能不佳的重要緣由。此外,須要在壓測時關注 G 是否頻繁切換,P 是否有飢餓等問題,有針對性的進行多核性能優化。
咱們再來看看長連接的模式,在這種模式下會有大量連接,但不會出現同時有大量流量的狀況。MOSN 針對這種場景提供了基於 NetPoll 的使用模式,咱們重點壓測了在 10K 連接場景下 SOFARPC 的性能。
從壓測結果上能夠看看到,基於 Raw Epoll 的 NetPoll 模式在資源消耗上明顯少於原生 Golang IO 的模式。
從結果上看,原生 IO模式還沒法高性能的知足 C10K 場景的要求,針對高性能網關場景仍是須要經過更有針對性的方案來支持。
最後我將介紹 TLS 性能數據,這裏經過 Nginx+OpenSSL,Caddy,Caddy+BoringSSL 三種實現來測試 SSL 處理的性能數據。
從測試結果能夠看到,對於 RSA 加密,使用了 Golang 原生支持的 Caddy 性能明顯弱與 OpenSSL 及Caddy+BoringSSL,但對於 ECDSA 來講 Caddy 弱於 OpenSSL,但明顯略好於經過 cgo 調用 BoringSSL 的方式。
經過進一步分析發現,Golang 對 RSA 的實現是基於 Golang 的,但對 ECDSA 等現代加密算法有彙編優化,好比說對 p256 的一些重點實現方法是移植了 OpenSSL 實現。同時 Golang 對 AES-GCM,SHA,MD 等算法都有彙編優化。若是你須要使用的算法正好在 Golang 的優化範圍內,那麼徹底能夠直接使用 Golang 原生實現,能夠省去對接 OpenSSL、BoringSSL 的麻煩。
最終總結一些性能優化的結果,到目前爲止,在 SOFARPC 協議上對 0.1.0 版本 QPS 提高了 50%,內存使用減小了 40%;HTTP/2.0 通過一輪優化,QPS 提高了一倍,後續會繼續推動優化;HTTP/1.1 也有 30% 以上的性能提高。
此外,Golang 性能優化與 C/C++ 仍是有比較大的區別,在C/C++ 優化過程當中,重點觀察系統 perf 進行優化,但Golang 的話須要既須要瞭解、觀察 Golang runtime 的 perf、調度數據,也須要觀察 OS層面 的 perf 數據,而且須要進行結合分析。一些 C/C++ 經常使用的方式在 Golang 也沒法直接使用,好比說在C中作無鎖替換常常經過整塊內存替換指針的方式來保證原子性,但在 Golang 裏指針替換並非原子的,若是分析彙編會發現實際上執行了多條彙編,在實現層面就須要一些特殊的處理。
因爲 Golang 從編譯到運行時,從運行單元到系統調用都是一個很是獨立而且自包含的體系,他並無基於 C 的開發套件創建,能夠說是很是自成一體了,因此在系統層面的集成上仍然有很多問題須要克服,好比說 cgo 性能,可是因爲他的優勢也是很是明顯的,能夠在更多系統軟件場景去探索挖掘,完善實現,創建出基於 Golang 世界的系統軟件體系。
此外,在解決具體問題的過程當中咱們積累了很多有值得分享的案例,好比說在大流量場景下動態更新存量連接的配置風險策略,Metrics 平滑遷移,支持多層路由判斷的可擴展鏈式路由等,受限於篇幅沒法一一展開,後續咱們將經過blog 或 meetup 的方式與你們分享。
最後咱們再看看微服務場景下 SOFAMosn 落地的方案,首先 SOFAMosn 做爲 Sidecar 與 SOFABoot APP 融合代理服務、通訊、配置等功能,與螞蟻的 Control Plane 通訊完成服務配置更新。
最後咱們再從總體視角看看 MOSN、MOSNG 在螞蟻架構中的位置。MOSN 做爲螞蟻全新的數據平面,會貫穿網絡接入、微服務、安全、Serverless 等場景的落地中。咱們將推動東西向,南北向技術架構的融合,造成統一的負載網絡。在安全方向上,咱們將會在微服務級別的安全保障上作更細緻的工做,從 二、三、四、7 層作更多的安全隔離工做,例如作到微服務粒度的流量攔截、牽引。在 Serverless 場景,MOSN 將做爲 Serving 的前置提供服務。最後 MOSN 將積極地與用戶態加速技術,7層流量攔截服務等基礎能力集成,更好的服務於統一負載網絡。 從螞蟻技術棧演進的視角看,在下一代微服務架構、下一代接入網絡、零可信微隔離的技術發展的萌芽之下,MOSN的出現是必然也是偶然,最終將成爲新生技術體系落地過程的重點環節,咱們將繼續探索,逐步造成適合螞蟻業務場景的數據平面。
我今天要介紹的內容就是這些,歡迎你們關注「金融級分佈式架構」,「ServiceMesher」 公衆號,咱們將會有更多技術乾貨發佈在公衆號中。同時這裏有 SOFAMesh、SOFAMosn 的 Github 地址,歡迎你們 star,或試用,更歡迎你們爲咱們提出寶貴意見。謝謝你們。 地址: SOFAMesh: github.com/alipay/sofa… SOFAMosn: github.com/alipay/sofa…
地址: www.sofastack.tech/posts/2018-…