螞蟻金服的 Service Mesh 演進之道?

螞蟻金服在服務化上面已經經過多年的沉澱,支撐了每年雙十一的高峰峰值。Service Mesh 作為微服務的個新方向,在最近兩年成為領域的一個大熱點,但是如何從經典服務化架構往 Service Mesh 的方向上演進,中間可能會遇到什麼樣的問題,幾乎沒有可以借鑑的經驗。

本文會給大家分享 Service Mesh 在螞蟻金服的演進歷程和在2018年6月舉辦的 GIAC 全球互聯網架構大會中螞蟻金服高級技術專家與現場人員關於Service Mesh的熱門QA互動。

蚂蚁金服的 Service Mesh 演进之道?

螞蟻金服高級技術專家,螞蟻金服分佈式架構SOFA 的開源負責人黃挺

前言

在過去的一段時間中螞蟻金服已經開始採用 Service Mesh 來幫助解決一些架構上的問題,並且在 Service Mesh 如何更好地與經典的服務化架構結合上有一定的經驗,希望藉此分享和大家交流我們這部分的實踐。使大家對螞蟻金服當前的服務化架構有更多瞭解,並對 Service Mesh 如何解決經典服務化架構中的問題以及螞蟻金服實際在落地Service Mesh 中的時候的一些設計考慮和未來展望有更進一步的瞭解,也希望能與行業分享螞蟻金服服務化架構現狀。

螞蟻金服從單體應用轉移到服務化的架構下已經經過了差不多 10 年的時間,在整個過程中,為了滿足螞蟻金服金融級的要求,我們也構建了一整套地面向金融級的分佈式架構的解決方案,也就是 SOFA。

SOFA 其實包含了金融級分佈式中間件,CICD 以及 PAAS 平臺。SOFA中間件部分包含的內容包括 SOFABoot 研發框架、SOFA微服務相關的框架(RPC,服務註冊中心,批處理框架,動態配置等等)、消息中間件、分佈式事務和分佈式數據訪問等等中間件。

以上的這些中間件都是基於 Java 技術棧的,目前 SOFA 在螞蟻金服內部大概超過 90% 的系統在使用,除了這些系統之外,還有剩下的 10% 的系統,採用 NodeJS,C++,Python 等等技術棧研發的。這剩下的 10% 的系統想要融入到 SOFA 的整個體系中,一種辦法是用對應的語言再去寫一遍 SOFA 中間件的各個部分對應的客戶端。

事實上,之前我們正是這麼幹的,螞蟻金服內部之前就有一套用 NodeJS 搞的 SOFA 各個組件的客戶端,但是最近幾年隨著 AI 等領域的興起,C++ 也在螞蟻金服內部也在被應用到越來越多的地方,那麼我們是否也要用 C++ 再來寫一遍 SOFA 中間件的各個客戶端?如果我們繼續採用這種方式去支持 C++ 的系統,首先會遇到成本上的問題,每個語言一套中間件的客戶端,這些中間件的客戶端就像一個個煙囪,都需要獨立地去維護,去升級。另一方面,從穩定性上來講,之前 Java 的客戶端踩過的一些坑,可能其他的語言又得重新再踩一遍坑。

對於多語言的問題來說,Service Mesh 其實就很好地解決了這部分的問題,通過 Service Mesh的方案,我們可以儘量把最多的功能從中間件的客戶端中移到 Sidecar 中,這樣就可以做到一次實現,就搞定掉所有語言,這個對於基礎設施團隊來說,在成本和穩定性上都是一個提升。

蚂蚁金服的 Service Mesh 演进之道?

另外的一個問題其實是所有在往雲原生架構中轉型的公司都會遇到的問題,雲原生看起來非常美好,但是我們怎麼漸進式的演進到雲原生的架構下?特別是對於遺留系統,到底怎麼做比較好。當然,一種簡單粗暴的方式就是直接用雲原生的設施和架構重新寫一套,但是這樣,投入的成本就非常高,而且重寫就意味著可能會引入 Bug,導致線上的穩定性的問題。那麼有沒有一種方式可以讓這些遺留系統非常便捷地享受到雲原生帶來的好處呢?Service Mesh 其實為我們指明瞭一個方向,通過 Service Mesh,我們為遺留系統安上一個 Sidecar,少量地修改遺留系統的配置甚至不用修改遺留系統的配置就可以讓遺留系統享受到服務發現,限流熔斷,故障注入等等能力。

蚂蚁金服的 Service Mesh 演进之道?

最後我們在螞蟻金服的服務化的過程中遇到的問題是中間件升級的問題,螞蟻金融從單體應用演進到服務化的架構,再演進到單元化的架構,再演進到彈性架構,其實伴隨了大量中間件升級,每次升級,中間件不用說要出新的版本去提供新的能力,業務系統也需要升級依賴的中間件,這中間再出個 Bug,又得重新升級一遍,不光是中間件研發同學痛苦,應用的研發同學也非常痛苦。

我們從單體應用演進到了服務化的架構,從原來好幾個團隊維護同一個應用,到各個團隊去維護各自領域的應用,團隊之間通過接口去溝通,已經將各個業務團隊之間做到了最大程度的解耦,但是對於基礎設施團隊來說,還是和每一個業務團隊耦合在一起。

我們中間嘗試過用各種方法去解決升級過程中的耦合的問題,一種是通過我們自己研發的應用服務器 CloudEngine 來管理所有的基礎類庫,儘量地去減少給用戶帶來的升級成本,不用讓用戶一個個升級依賴,一次升級就可以。

但是隨著螞蟻的業務的不斷髮展,規模地不斷擴大,團隊的數量,業務的規模和我們交付的效率已經成為了主要的矛盾,所以我們期望以更高的效率去研發基礎設施,而不希望基礎設施的迭代受制於這個規模。

後來螞蟻自己研發的數據庫 OceanBase 也在用一個 Proxy 的方式來屏蔽掉 OceanBase 本身的集群負載,FailOver切換等方面的邏輯,而剛好 Service Mesh 的這種 Sidecar 的模式也是這樣的一個思路,這讓我們看到將基礎設施的能力從應用中下移到 Sidecar 這件事情是一個業界的整體的趨勢和方向,通過這種方式應用和中間件的基礎設施從此成了兩個進程,我們可以針對中間件的基礎設施進行單獨的升級,而不用和應用的發佈升級綁定在一起,這不僅解放了應用研發和基礎設施團隊,也讓基礎設施團隊的交付能力變地更強,以前可能需要通過半年或者一年甚至更長時間的折騰,才能夠將基礎設施團隊提供的新的能力鋪到所有的業務系統中去,現在我們通過一個月的時間,就可以將新能力讓所有的業務系統享受到。這也讓基礎設施團隊的中臺能力變得更強了。這樣我們就可以把我們還是把一些架構當中非常關鍵的支撐點以及一些邏輯下沉到 Sidecar上面去,因為整個螞蟻金服的整體架構有非常多的邏輯和能力承載在這一套架構上面的。這些東西我們有一個最大的職責是要支撐它快速向前演進和靈活。

蚂蚁金服的 Service Mesh 演进之道?

Service Mesh 的選型

前面講到了螞蟻金服當前服務化架構下遇到的問題以及我們希望能夠通過 Service Mesh 能夠去解決的一些問題,接下來就面臨一個很現實的問題,Service Mesh 的框架我們到底應該怎麼選,我們應該用什麼樣的標準去衡量,那接下來,我就給大家分享一下螞蟻金服在Service Mesh 的框架上的選型上的一些思考。

首先,所有的架構的演進都不是一蹴而就的,都是一個漸進式地演進的一個過程,越大的公司在架構演進的過程中其實越需要考慮這一點。所以我們在選型的時候就需要去考慮這一點,考慮目標框架能否很好地和當前的架構融合在一起。另一個點,作為一個和錢打交道的公司,我們需要特別地去關注目標框架是否在生產環境經過大規模的驗證,在場景上,是否經過了各類場景的驗證。

目前,業界主流的 Service Mesh 相關的框架有三個,分別是 Google,IBM,Lyft都參與其中的 Istio,以及 Bouyant 公司下的兩個開源的 Service Mesh 的框架 Linkerd 以及 Conduit。

首先我們來看下 Istio,Istio 應該是目前被關注最高的一個 ServiceMesh 框架,本身又有頂尖公司的光環加持,比如 Google,IBM 等等,他也完整地包含了一個 Data Plane 以及 Control Plane,但是Istio 一直以來被挑戰的地方其實在於他的 Control Plane 的 Mixer 的部分,Istio 的 Mixer 承擔了服務鑑權,Quota 控制,Tracing,Metrics等等能力,它是一箇中央的節點,如果不開啟緩存的情況下,所有的調用都需要從 Mixer 中去過,即使開啟了緩存的情況,也不可避免的有請求一定要從 Mixer 中去過,而在全螞蟻,有20000 多的服務,服務之間的調用是非常頻繁的,如果都需要過 Mixer,那 Mixer 就成了一個單點,這個單點的運維和高可用又成了一個問題。

另外,Istio 的性能是我們一直以來比較擔心的問題,雖然 Istio 每個版本的發佈,性能都有了一定程度的提升。但是我們來看下 Istio 的性能數據,0.5.1 的時候是 700 的 TPS,0.6.0 的時候是 1000 個 TPS,0.7.1 的時候是 1700 個 TPS,相對於一般的RPC 通信框架,最低最低都是萬級別的 TPS,Istio 的這個性能數據的確是有點兒慘淡,完全無法滿足螞蟻這邊的性能要求。

接下來我們來看 Linkerd,Linkerd 算是業界幾個 Service Mesh的框架裡面最成熟的一個了,但是他也有一個問題,首先就是他脫胎於 Twitter 的 Finagle,架構上其實不夠開放,沒法很好的適配到螞蟻的環境裡面去,另外Linkerd 也沒有 Control Plane 這一層,只有 Sidecar,再者 Linkerd 的路由規則 DTab 其實是挺難理解的。最後,其實也是我們當時選型的時候最關心的一個問題,Linkerd是用 Scala 寫的,跑在 JVM 上面,我從 Linkerd 的一篇博客上摘錄出了一張圖片,這篇博客主要講的是如何優化 JVM 的內存使用,這種文章一般上是的確有這個問題,才會去寫這樣的文章,從這張圖片中我們可以看到 Linkerd 所需要的內存至少都需要 100M,這也是 Bouyant 官方不推薦 Linkerd 和應用做一對一的部署,而是採用 DaemonSet 的方式進行部署。而我們期望的一個部署方式是和應用做一對一的部署,這樣的內存佔用對於我們來說成本太過,我們期望將 Sidecar 的內存佔用控制在 10M 左右。

最後,我們來看下 Conduit,首先 Conduit 也是 Linkerd 不久之前推出的一個Service Mesh 的框架,其實不太成熟,其次,Conduit 選擇的語言是 Rust,我們來看下 Rust 在 Tiebo 上的排名,Java 長時間高居第一位,C++在第三位,Golang 經過這幾年雲基礎設施的蓬勃發展,到了 14 位,而 Rust,和一眾語言的佔用率沒有太大的差別,排在了 50 位往後。

所以,我們最後選擇了自研 Service Mesh,一方面當然是我們基於前面的兩個準則去衡量目前業界流行的Service Mesh 框架,沒有能夠完全滿足我們的要求的,另一方面螞蟻金服服務化上有長期以及深厚的積累,這部分的一些經驗也可以支持我們能夠更好地去自研我們自己的Service Mesh 的框架。

當然,我們也不是說完全從零開始搞 Service Mesh 框架,對於業界的Service Mesh 的框架中的優秀理念,我們是希望能夠吸收過來的,另一方面,我們也希望能夠儘量地去 Follow Service Mesh 目前社區中的一些規範。

SOFA Mesh 的設計

首先,SOFA Mesh 其實直接採用了 Istio 的 Control Plane 的Pilot 和 Auth,因為我們覺得 Istio 在這塊上沒有太大的問題甚至裡面也有一些非常不錯的設計,比如Pilot 這部分的 Universal Data API 就是非常不錯的設計。Istio 的 Auth 這部分也充分地利用了 Kubernetes 的安全機制。

而Mixer 這部分,其實我之前就提到我們是覺得有設計上問題的,所以我們的想法是直接把 Mixer 搬到 Sidecar 中實現。

再者,大家都知道 Istio 的 Sidecar 是 Envoy,它是一個用 C++ 寫的,那麼我們怎麼把Mixer 移入到 Sidecar 中去呢,其實我們的 SOFA Mesh 的 Sidecar 是採用了 Golang 來寫的,所以才給把 Mixer 移入Sidecar 提供了可能性,當然,我們選擇用 Golang 來研發 Sidecar 不僅僅是為了把 Mixer 移入到 Sidecar 而已,其實也有其他的考慮,一方面,在雲計算的時代,Golang以及成為構建基礎設施的首選語言,我們看到大量的基礎設施都是用 Golang 寫的,包括 Docker,Kubernetes 等等,選擇 Golang,其實也是希望能夠更好地和雲原生時代的這些基礎設施貼合。

另外,相比於 Envoy 採用的 C++,Golang 顯然更加容易上手,也更加容易找到這方面的人才,另外,Golang相對於 JVM 來說,Memory Footprint 低了非常多,我們用 Golang 寫的 Sidecar,目前的峰值 TPS 下的內存在用在 11M,雖然還有一定的優化空間,但是相比於 JVM 來說,已經降低了10 倍。

另外,雖然我們採用了 Istio 的 Pilot,但是在內部使用的時候,直接使用Pilot 並不能滿足我們的訴求。首先,Pilot 在 Kubernetes 上是直接對接到 Kubernetes 的服務發現機制上的,無論是 SOFARPC,還是微博的Motan 等等國內的服務框架,其實都是單個應用多個服務這樣的模型,而 Kubernetes 的服務發現機制實際上針對的是單個應用單個服務的模型,在模型上就不太一致。另外,SOFA的服務註冊中心 SOFARegistry 在螞蟻金服內部經過了多年的實踐,面對內部大規模的服務化的場景,SOFARegistry 的擴展能力以及可靠性已經經過了大量的實踐證明,這裡說一下SOFARegistry 上的一些數據,上面大約註冊了 2W 多個服務,一個機房裡面的 Pub 和 Sub 的加起來在千萬級別。基於以上的考慮,我們選擇了用Pilot 上增加 SOFARegistry 的 Adapter,使之能夠拿到 SOFARegistry 上的服務註冊信息。

然後,Pilot 還有一個問題,就是原來 Pilot 會把所有的服務註冊相關的數據都同步到Pilot 上,這個對於 Pilot 的集群的壓力是非常大的,所以我們選擇了只同步必要的數據到一個 Pilot 的節點上,減少 Pilot 本身的內存壓力。

最後,我再分享一個螞蟻金服的場景,在螞蟻金服,因為事業部眾多以及監管的問題,不用的事業部之間的一些機器可能是網絡不通的,那麼他們要做服務訪問,就必須有一個角色來做跨環境之間的服務訪問,所以我們基於 Sidecar 的概念,提出了 EdgeSidecar 的角色,他在技術的實現細節上其實和和應用部署在一起的 Sidecar 是非常類似的,只是這個 Sidecar 作為一個“邊緣”的角色,來負責跨環境的服務通信問題。

所以,SOFA Mesh 在整體的大圖上大概是這樣的,我們自研了一個 Golang 的Sidecar,並且把 Mixer 納入到 Sidecar 中,來防止出現類似於 Istio 那樣的性能問題,在 Pilot 和 Auth 這兩個角色了,我們選擇直接使用Istio 的,然後在上面做一定程度的適配,適配到螞蟻內部的環境中,然後我們在整個部署上,新增了一個 EdgeSidecar 的角色,來解決跨環境的服務調用的問題。

蚂蚁金服的 Service Mesh 演进之道?

我知道大家一定對 SOFA Mesh 在螞蟻內部的落地情況非常感興趣,目前我們已經落地的場景主要是多語言的場景,解決其他的語言和 SOFA 的通信問題,大約上了二三十個系統。然後我們正在嘗試用 SOFA Mesh 去更好地解決服務間調用的安全,以及藍綠髮布的問題,在異構系統通信的這件事情上,我們也在不久的將來會嘗試用 SOFA Mesh 去解決。

當然,SOFA Mesh 在螞蟻內部的落地其實離不開開源社區,所以在未來的兩三個月內,我們也會將 SOFA Mesh 開源出來,將螞蟻內部實踐 Service Mesh 的成果開源出來,給大家更多在這方面的參考。

對於未來,其實我覺得中間件作為基礎設施未來和雲平臺融合是一個不可阻擋地趨勢,除了 Service Mesh,未來還可能會出現 Message Mesh,DB Mesh 等等產品,我知道業界有些同學已經開始做這方面的努力了。最後總結一下我今天演講的內容,一個是 Service Mesh 給螞蟻金服解決的問題,包括多語言,遺留系統以及基礎設施團隊和業務團隊耦合的問題。在 ServiceMesh 的選型上,我們主要考量和當前架構的可融合性,以及框架的高可用,穩定性。未來除了 ServiceMesh,可能還會出現其他的 Mesh,中間件和底層雲平臺進一步融合的趨勢不可擋。多謝大家!

下面帶來的是GIAC大會中螞蟻金服高級技術專家與現場參會人員進行關於Service Mesh的問答互動,我們精選了幾個比較熱門的問答分享給大家。

蚂蚁金服的 Service Mesh 演进之道?

一、Mesh的高可用和安全,能否詳細說明一下?

答:我們最近正在做安全這件事情,安全涉及到兩個方面,一個方面是 RPC 的整個服務調用健全的問題,這個是可以直接在 Mesh 中去做的,可以直接利用 Istio 的 RBAC 來實現,另外是 Mesh 和 Mesh 之間的 TLS雙向認證的事情。這個其實 Istio 裡面會有一些現成的方案,它與 K8S 融合的也非常好,這些東西是可以直接拿過來去用的。

二、如何解決服務的多版本路由和數據單元的多版本路由的問題?

答:ServiceMesh 主要關注的是服務調用這一塊,我來解釋一下多版本的路由,其實我們在內部的話,服務版本這件事情用得會比較少,用得更多的是同一服務不同的實現。但是其實多版本路由這一塊,如果說大家知道 K8S 的 Label 的話,可以把它的這種設計來借鑑到整個Mesh當中,然後通過不同的標籤來做區分,後面也會有一些這方面的分享出來。

三、Service Mesh 主要是解決了請求的可靠傳輸和服務治理的問題嗎?

答:應該是說Service Mesh提出了更好的方式去解決請求的可靠傳輸和服務治理的問題。其實想像一下,如果說你要上一整套的服務治理的架構的話,在原來的方式下可能需要你們所有的上層業務系統都接入你們對應的服務治理的組件,現在的話,只要有一個Service Mesh,在這個 Sidecar 當中就可以把服務治理的這件事情做掉。它沒有去解決新的問題,只是把一些老的問題用更好的方式去解決。

四、為什麼Control Plane對於Mesh來說很重要?

答:其實這個就涉及到整個雲平臺和我們整個服務化體系的融合的問題。其實目前大家可以看到,Pilot 這部分的東西,在原來 Istio 設計當中是非常強的和 K8S 這個東西融合在一起的,如果說你沒有這套東西存在的話,對於 Mesh 來說還是一個非常上層的中間件這樣的東西。當然你可以說不用 Control Plane 這一層,只有 Sidecar,對接到原來的一整套的服務治理體系當中去,這樣做也是可以的,沒有太大的問題。但是有了 Control Plane 這一層東西,它定義了非常通用的 API,本身這個架構又是和雲平臺整個架構是綁定得比較緊的,有更好的融合度。所以我們覺得整個Control Plane這一層是非常重要的。

另外,Istio 提出 Control Plane,其實是在往微服務標準化方面邁進了很大一層。它裡面有非常多的服務發現的標準,治理的標準,雖然說他大膽提出了這樣的概念和假設,我們也看到了它的一些不足,所以我們希望和社區一起推進這一層的標準化。就像我一開始分享的,基礎設施一層一層的向上包。像我們覺得越來越多的中間件的部分,其實是會被沉澱到基礎設施當中的。現在也有云原生語言,我們編譯了一下,發現很慢,問題也很多,但是我們覺得這是一個方向。大家在寫的時候,可能就用這樣的語言去寫,很多能力就提升上去了。我們希望把基礎設施向上再推一下,去扮演這樣一個角色。這也是我們認為 Control Plane 的最大的價值。

號外【 招人啦!】

RUST這個語言現在比較新,我們雖然現在不太敢用在中間件方向上,因為畢竟這個方向上承載了太多基礎設施的使命。但是我們在一些小的方向上在嘗試,因為大家知道 RUST 發展得還是很不錯的,而且這個語言確實有天生的優勢,我們也在招這方面的人,內部也有一些這樣的同學,我們想在持續數據庫和軟硬件結合方向上再做一些嘗試,大家有興趣歡迎砸簡歷來~!


分享到:


相關文章: