一、引言
Service Mesh 是螞蟻金服下一代架構的核心,經過了2年的沉澱,我們探索出了一套切實可行的方案并最終通過了雙十一的考驗。本文主要分享在當下『路口』,我們在産品設計上的思考和實踐,希望能給大家帶來一些啟發。
二、為什麼需要 Service Mesh?
2.1 微服務治理與業務邏輯解耦
在 Service Mesh 之前,微服務體系的玩法都是由中間件團隊提供一個 SDK 給業務應用使用,在 SDK 中會內建各種服務治理的能力,如:服務發現、負載均衡、熔斷限流、服務路由等。
在運作時,SDK 和業務應用的代碼其實是混合在一個程序中運作的,耦合度非常高,這就帶來了一系列的問題:
- 更新成本高
-
- 每次更新都需要業務應用修改 SDK 版本号,重新釋出。
- 在業務飛速往前跑的時候,是不太願意停下來做這些和自身業務目标不太相關的事情的。
- 版本碎片化嚴重
-
- 由于更新成本高,但中間件還是會向前發展,久而久之,就會導緻線上 SDK 版本各不統一、能力參差不齊,造成很難統一治理
- 中間件演進困難
-
- 由于版本碎片化嚴重,導緻中間件向前演進過程中就需要在代碼中相容各種各樣的老版本邏輯,戴着『枷鎖』前行,無法實作快速疊代
有了 Service Mesh 之後,我們就可以把 SDK 中的大部分能力從應用中剝離出來,拆解為獨立程序,以 Sidecar 的模式部署。通過将服務治理能力下沉到基礎設施,可以讓業務更加專注于業務邏輯,中間件團隊則更加專注于各種通用能力,真正實作獨立演進,透明更新,提升整體效率。

2.2 異構系統統一治理
随着新技術的發展和人員更替,在同一家公司中往往會出現使用各種不同語言、不同架構的應用和服務,為了能夠統一管控這些服務,以往的做法是為每種語言、每種架構都重新開發一套完整的 SDK,維護成本非常高,而且對中間件團隊的人員結構也帶來了很大的挑戰。
有了 Service Mesh 之後,通過将主體的服務治理能力下沉到基礎設施,多語言的支援就輕松很多了,隻需要提供一個非常輕量的 SDK、甚至很多情況都不需要一個單獨的 SDK,就可以友善地實作多語言、多協定的統一流量管控、監控等治理需求。
2.3 金融級網絡安全
目前很多公司的微服務體系建設都建立在『内網可信』的假設之上,然而這個原則在目前大規模上雲的背景下可能顯得有點不合時宜,尤其是涉及到一些金融場景的時候。
通過 Service Mesh,我們可以更友善地實作應用的身份辨別和通路控制,輔之以資料加密,就能實作全鍊路可信,進而使得服務可以運作于零信任網絡中,提升整體安全水位。
三、在當下『路口』的思考
3.1 雲原生方案?
正因為 Service Mesh 帶來了上述種種的好處,是以這兩年社群中對 Service Mesh 的關注度越來越高,也湧現出了很多優秀的 Service Mesh 産品,Istio 就是其中一款非常典型的标杆産品。
Istio 以其前瞻的設計結合雲原生的概念,一出現就讓人眼前一亮,心之向往。不過深入進去看了之後發現,在目前階段要落地的話,還是存在一些 gap 的。
3.2 Greenfield vs Brownfield
在正式展開讨論之前,我們先來看一副漫畫。
上面這幅漫畫描繪了這樣一個場景:
- 有兩個勞工在工作,其中一個在綠色的草地(Greenfield)上,另一個在棕色的土地(Brownfield)上
- 在綠色草地上的勞工對在棕色土地上的勞工說:“如果你沒有給自己挖這麼深的坑,那麼你也可以像我一樣做一些很棒的新東西”
- 然後在棕色土地上的勞工回答道:“你倒是下來試試!”
這是一幅很有意思的漫畫,從表面上看我們可以認為在綠色草地上的勞工是站着說話不腰疼,不過其實本質的原因還是兩者所處的環境不同。
在一片未開發過的土地上施工确實是很舒服的,因為空間很大,也沒有周遭各種限制,可以使用各種新技術、新理念,我們國家近幾十年來的一些新區新城的建設就屬于這類。而在一片已經開發過的土地上施工就大不一樣了,周圍環境會有各種限制,比如地下可能有各種管線,一不小心就挖斷了,附近還有各種大樓,稍有不慎就可能把樓給挖塌了,是以做起事來就要非常小心,設計方案時也會受到各種限制,無法自由發揮。
對于軟體工程,其實也是一樣的,Greenfield 對應着全新的項目或新的系統,Brownfield 對應着成熟的項目或遺留系統。
我相信大部分程式員都是喜歡做全新的項目的,包括我自己也是一樣。因為可以使用新的技術、新的架構,可以按照事物本來的樣子去做系統設計,自由度很高。而在開發/維護一個成熟的項目時就不太一樣了,一方面項目已經穩定運作,邏輯也非常複雜,是以無法很友善地換成新的技術、新的架構,在設計新功能時也會礙于已有的架構和代碼實作做很多妥協,另一方面前人可能不知不覺挖了很多坑,稍有不慎就會掉進坑裡,是以行事必須要非常小心,尤其是在做大的架構改變的時候。
3.3 現實場景
3.3.1 Brownfield 應用當道
在現實中,我們發現目前大部分的公司還沒有走向雲原生,或者還剛剛在開始探索,是以大量的應用其實還跑在非 k8s 的體系中,比如跑在虛拟機上或者是基于獨立的服務注冊中心建構微服務體系。
雖然确實有少量 Greenfield 應用已經在基于雲原生來建構了,但現實是那些大量的 Brownfield 應用是公司業務的頂梁柱,承載着更大的業務價值,是以如何把它們納入 Service Mesh 統一管控,進而帶來更大的價值,也就成了更需要優先考慮的話題。
獨立的服務注冊中心
3.3.2 雲原生方案離生産級尚有一定距離
另一方面,目前 Istio 在整體性能上還存在一些有待解決的點(引述小劍老師在
螞蟻金服 Service Mesh 深度實踐中的觀點):
- Mixer
-
- Mixer 的性能問題,一直都是 Istio 中最被人诟病的地方。
- 尤其在 Istio 1.1/1.2 版本之後引入了 Out-Of-Process Adapter,更是雪上加霜。
- 從落地的角度看,Mixer V1 糟糕至極的性能,已經是“生命無法承受之重”。對于一般規模的生産級落地而言,Mixer 性能已經是難于接受,更不要提大規模落地……
- Mixer V2 方案則給了社群希望:将 Mixer 合并進 Sidecar,引入 web assembly 進行 Adapter 擴充,這是我們期待的 Mixer 落地的正确姿勢,是 Mixer 的未來,是 Mixer 的『詩和遠方“。然而社群望穿秋水,但Mixer V2 遲遲未能啟動,長期處于 In Review 狀态,遠水解不了近渴。
- Pilot
-
- Pilot 是一個被 Mixer 掩蓋的重災區:長期以來大家的性能關注點都在 Mixer,表現糟糕而且問題明顯的Mixer 一直在吸引火力。但是當選擇放棄 Mixer(典型如官方在 Istio 新版本中提供的關閉 Mixer 的配置開關)之後,Pilot 的性能問題也就很快浮出水面。
- 我們實踐下來發現 Pilot 目前主要有兩大問題:1)無法支撐海量資料 2)每次變化都會觸發全量推送,性能較差
3.4 當下『路口』我們該怎麼走?
我們都非常笃信雲原生就是未來,是我們的『詩和遠方』,但是眼下的現實情況是一方面 Brownfield 應用當道,另一方面雲原生的 Service Mesh 方案自身離生産級還有一定的距離,是以在當下這個『路口』我們該怎麼走?
我們給出的答案是:
其實如前面所述,我們采用 Service Mesh 方案的初心是因為它的架構改變可以帶來很多好處,如:服務治理與業務邏輯解耦、異構語言統一治理、金融級網絡安全等,而且我們相信這些好處不管對 Greenfield 應用還是 Brownfield 應用都是非常需要的,甚至在現階段對 Brownfield 應用産生的業務價值會遠遠大于 Greenfield 應用。
是以從『務實』的角度來看,我們首先還是要探索出一套現階段切實可行的方案,不僅要支援 Greenfield 應用,更要能支援 Brownfield 應用,進而可以真正把 Service Mesh 落到實處,産生業務價值。
四、螞蟻金服的産品實踐
4.1 發展曆程和落地規模
Service Mesh 在螞蟻金服的發展曆程,先後經曆過如下幾個階段:
- 技術預研 階段:2017年底開始調研并探索 Service Mesh 技術,并确定為未來發展方向。
- 技術探索 階段:2018年初開始用 Golang 開發 Sidecar SOFAMosn ,年中開源基于 Istio 的 SOFAMesh 。
- 小規模落地 階段:2018年開始内部落地,第一批場景是替代 Java 語言之外的其他語言的用戶端 SDK,之後開始内部小範圍試點。
- 規模落地 階段:2019年上半年,作為螞蟻金融級雲原生架構更新的主要内容之一,逐漸鋪開到螞蟻金服内部的業務應用,并平穩支撐了618大促。
- 對外輸出 階段:2019年9月,SOFAStack 雙模微服務平台入駐阿裡雲開始公測,支援 SOFA, Dubbo 和 Spring Cloud 應用
- 全面大規模落地 階段:2019年下半年,在螞蟻主站的大促核心應用中全面鋪開,落地規模非常龐大,而且最終如『絲般順滑』地支撐了雙十一大促。
在今年雙十一,Service Mesh 覆寫了數百個交易核心鍊路應用,SOFAMosn 注入的容器數量達到了數十萬(據信是目前全球最大的 Service Mesh 叢集),雙十一當天處理的 QPS 達到了幾千萬,平均處理響應時間<0.2 ms,SOFAMosn 本身在大促中間完成了數十次的業務無感更新,達到了我們的預期,初步完成了基礎設施和業務的第一步的分離,見證了 Mesh 化之後基礎設施的疊代速度。
4.2 SOFAStack 雙模微服務平台
我們的服務網格産品名是 SOFAStack 雙模微服務平台,這裡的『雙模微服務』是指傳統微服務和 Service Mesh 雙劍合璧,即『基于 SDK 的傳統微服務』可以和『基于 Sidecar 的 Service Mesh 微服務』實作下列目标:
• 互聯互通:兩個體系中的應用可以互相通路
• 平滑遷移:應用可以在兩個體系中遷移,對于調用該應用的其他應用,做到透明無感覺
• 異構演進:在互聯互通和平滑遷移實作之後,我們就可以根據實際情況進行靈活的應用改造和架構演進
在控制面上,我們引入了 Pilot 實作配置的下發(如服務路由規則),在服務發現上保留了獨立的 SOFA 服務注冊中心。
在資料面上,我們使用了自研的 SOFAMosn,不僅支援 SOFA 應用,同時也支援 Dubbo 和 Spring Cloud 應用。
在部署模式上,我們不僅支援容器/k8s,同時也支援虛拟機場景。
4.3 大規模場景下的服務發現
要在螞蟻金服落地,首先一個需要考慮的就是如何支撐雙十一這樣的大規模場景。前面已經提到,目前 Pilot 本身在叢集容量上比較有限,無法支撐海量資料,同時每次變化都會觸發全量推送,無法應對大規模場景下的服務發現。
是以,我們的方案是保留獨立的 SOFA 服務注冊中心來支援千萬級的服務執行個體資訊和秒級推送,業務應用通過直連 Sidecar 來實作服務注冊和發現。
4.4 流量劫持
Service Mesh 中另一個重要的話題就是如何實作流量劫持:使得業務應用的 Inbound 和 Outbound 服務請求都能夠經過 Sidecar 處理。
差別于社群的 iptables 等流量劫持方案,我們的方案就顯得比較簡單直白了,以下圖為例:
- 假設服務端運作在1.2.3.4這台機器上,監聽20880端口,首先服務端會向自己的 Sidecar 發起服務注冊請求,告知 Sidecar 需要注冊的服務以及 IP + 端口(1.2.3.4:20880)
- 服務端的 Sidecar 會向 SOFA 服務注冊中心發起服務注冊請求,告知需要注冊的服務以及 IP + 端口,不過這裡需要注意的是注冊上去的并不是業務應用的端口(20880),而是Sidecar自己監聽的一個端口(例如:20881)
- 調用端向自己的 Sidecar 發起服務訂閱請求,告知需要訂閱的服務資訊
- 調用端的Sidecar向調用端推送服務位址,這裡需要注意的是推送的IP是本機,端口是調用端的 Sidecar 監聽的端口(例如:20882)
- 調用端的 Sidecar 會向 SOFA 服務注冊中心發起服務訂閱請求,告知需要訂閱的服務資訊
- SOFA 服務注冊中心向調用端的 Sidecar 推送服務位址(1.2.3.4:20881)
經過上述的服務發現過程,流量劫持就顯得非常自然了:
- 調用端拿到的『服務端』位址是127.0.0.1:20882,是以就會向這個位址發起服務調用
- 調用端的 Sidecar 接收到請求後,通過解析請求頭,可以得知具體要調用的服務資訊,然後擷取之前從服務注冊中心傳回的位址後就可以發起真實的調用(1.2.3.4:20881)
- 服務端的 Sidecar 接收到請求後,經過一系列處理,最終會把請求發送給服務端(127.0.0.1:20880)
可能會有人問,為啥不采用 iptables 的方案呢?主要的原因是一方面 iptables 在規則配置較多時,性能下滑嚴重,另一個更為重要的方面是它的管控性和可觀測性不好,出了問題比較難排查。
4.5 平滑遷移
平滑遷移可能是整個方案中最為重要的一個環節了,前面也提到,在目前任何一家公司都存在着大量的 Brownfield 應用,它們有些可能承載着公司最有價值的業務,稍有閃失就會給公司帶來損失,有些可能是非常核心的應用,稍有抖動就會造成故障,是以對于 Service Mesh 這樣一個大的架構改造,平滑遷移是一個必選項,同時還需要支援可灰階和可復原。
得益于獨立的服務注冊中心,我們的平滑遷移方案也非常簡單直白:
1.初始狀态
以一個服務為例,初始有一個服務提供者,有一個服務調用者。
2.透明遷移調用方
在我們的方案中,對于先遷移調用方還是先遷移服務方沒有任何要求,這裡假設調用方希望先遷移到 Service Mesh 上,那麼隻要在調用方開啟 Sidecar 的注入即可,服務方完全不感覺調用方是否遷移了。是以調用方可以采用灰階的方式一台一台開啟 Sidecar,如果有問題直接復原即可。
3.透明遷移服務方
假設服務方希望先遷移到 Service Mesh 上,那麼隻要在服務方開啟 Sidecar 的注入即可,調用方完全不感覺服務方是否遷移了。是以服務方可以采用灰階的方式一台一台開啟 Sidecar,如果有問題直接復原即可。
4.終态
4.6 多協定支援
考慮到目前大部分使用者的使用場景,除了 SOFA 應用,我們同時也支援 Dubbo 和 Spring Cloud 應用接入SOFAStack 雙模微服務平台,提供統一的服務治理。多協定支援采用通用的
x-protocol,未來也可以友善地支援更多協定。
4.7 虛拟機支援
在雲原生架構下,Sidecar 借助于 k8s 的 webhook/operator 機制可以友善地實作注入、更新等運維操作。然而大量系統還沒有跑在 k8s 上,是以我們通過 agent 的模式來管理 Sidecar 程序,進而可以使 Service Mesh 能夠幫助老架構下的應用完成服務化改造,并支援新架構和老架構下服務的統一管理。
4.8 産品易用性
在産品易用性上我們也做了不少工作,比如可以直接在界面上友善地設定服務路由規則、服務限流等,再也不用手工寫 yaml 了:
也可以在界面上友善地檢視服務拓撲和實時監控:
4.9 阿裡雲公測中
最後打一個小小的廣告,SOFAStack 雙模微服務平台現在在阿裡雲公測中,歡迎感興趣的企業前來體驗,
https://www.aliyun.com/product/sofa。
五、展望未來
5.1 擁抱雲原生
目前已經能非常清楚地看到整個行業在經曆從雲托管(Cloud Hosted)到雲就緒(Cloud Ready)直至雲原生(Cloud Native)的過程,是以前面也提到我們都非常笃信雲原生就是未來,是我們的『詩和遠方』,雖然眼下在落地過程中還存在一定的 gap,不過相信随着我們的持續投入,gap 會越來越小。
另外值得一提的是我們擁抱雲原生其根本還在于降低資源成本,提升開發效率,享受生态紅利,是以雲原生本身不是目的,而是手段,切不可本末倒置了。
5.2 持續加強 Pilot 的能力
為了更好地擁抱雲原生,後續我們也會和 Istio 社群共建,持續加強 Pilot 的能力。
而就在最近,在綜合了過去一年多的思考和探索之後,螞蟻金服和阿裡集團的同僚們共同提出了一套完整的解決方案,來融合控制平面和傳統注冊中心/配置中心,進而可以在保持協定标準化的同時,加強 Pilot 的能力,使其逐漸向生産級靠攏。
(更多細節可以參考小劍老師的
一文,在此就不再贅述了)
5.3 支援透明劫持
前面提到在螞蟻金服的實踐中是基于服務注冊中心來實作流量劫持的,該方案不管是在性能、管控能力還是可觀測性方面都是不錯的選擇,不過對應用存在一定的侵入性(需要引入一個輕量的注冊中心 SDK)。
考慮到很多使用者對性能要求沒那麼敏感,同時有大量遺留系統希望通過 Service Mesh 實作統一管控,是以後續我們也會支援透明劫持,同時在管控性和可觀測性方面會做增強。
六、結語
基于『務實』的理念,Service Mesh 在螞蟻金服經過了2年的沉澱,我們探索出了一套現階段切實可行的方案并最終通過了雙十一的考驗。在這個過程中,我們也愈發體驗到了 Service Mesh 帶來的好處,例如 SOFAMosn 在大促中間完成了數十次的業務無感更新,見證了 Mesh 化之後基礎設施的疊代速度。
我們判斷,未來 Service Mesh 會成為雲原生下微服務的标準解決方案,是以我們也會持續加大對 Service Mesh 的投入,包括接下來螞蟻金服将和阿裡集團一起深度參與到 Istio 社群中去,和社群一起把 Istio 打造成 Service Mesh 的事實标準。
最後,也歡迎志同道合的夥伴加入我們,一起參與建設激動人心的下一代雲原生架構!