天天看點

幹貨 | 螞蟻金服是如何實作經典服務化架構往 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 作為一個“邊緣”的角色,來負責跨環境的服務通信問題。

幹貨 | 螞蟻金服是如何實作經典服務化架構往 Service Mesh 方向的演進的?

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

我知道大家一定對 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 的最大的價值。