本文節選自《不一樣的 雙11 技術:阿裡巴巴經濟體雲原生實踐》一書
作者:
黃挺,花名魯直,螞蟻金服微服務以及雲原生方向負責人,主導螞蟻金服的雲原生落地。
雷志遠,花名碧遠,螞蟻金服 RPC 架構負責人
更多雲原生技術資訊可關注
阿裡巴巴雲原生技術圈 。引言
Service Mesh 是螞蟻金服下一代架構的核心,本主題主要分享在螞蟻金服目前的體量下,我們如何做到在奔跑的火車上換輪子,将現有的 SOA 體系快速演進至 Service Mesh 架構。聚焦 RPC 層面的設計和改造方案,分享螞蟻金服 雙11 核心應用如何将現有的微服務體系平滑過渡到 Service Mesh 架構下并降低大促成本。
螞蟻金服每年 雙11 大促會面臨非常大的流量挑戰,在已有 LDC 微服務架構下已支撐起彈性擴容能力。本次分享主要分為 4 部分:
- Service Mesh 簡介;
- 為什麼要 Service Mesh;
- 我們的方案是什麼;
- 分時排程案例;
Service Mesh 簡介
在講具體的螞蟻金服落地之前,想先和大家對齊一下 Service Mesh 的概念,和螞蟻金服對應的産品。
這張圖大家可能不陌生,這是業界普遍認可的 Service Mesh 架構,那麼對應到螞蟻金服,螞蟻金服的 Service Mesh 也分為控制面和資料面,分别叫做 SOFAMesh 和 SOFAMosn,其中 SOFAMesh 後面會以更加開放的姿态參與到 Istio 裡面去。
今天我們講的實踐主要集中在 SOFAMosn 上,以下我的分享中提到的主要就是集中在資料面上的落地,這裡面大家可以看到,我們有支援 HTTP/SOFARPC/Dubbo/WebService。
為什麼我們要 Service Mesh
有了一個初步的了解之後,可能大家都會有這樣一個疑問,你們為什麼要 Service Mesh,我先給出結論:
因為我們要解決在 SOA 下面,沒有解決但亟待解決的:基礎架構和業務研發的耦合,以及未來無限的對業務透明的穩定性與高可用相關訴求。
那麼接下來,我們一起先看看在沒有 Service Mesh 之前的狀況。
在沒有 Service Mesh 之前,整個 SOFAStack 技術演進的過程中,架構和業務的結合相當緊密,對于一些 RPC 層面的需求,比如流量排程,流量鏡像,灰階引流等,是需要在 RPC 層面進行更新開發支援,同時,需要業務方來更新對應的中間件版本,這給我們帶來了一些困擾和挑戰。如圖所示:
- 線上用戶端架構版本不統一;
- 業務和架構耦合,更新成本高,很多需求由于在用戶端無法推動,需要在服務端做相應的功能,方案不夠優雅;
- 機器逐年增加,如果不增加機器,如何度過 雙11;
- 在基礎架構準備完成後,對于新功能,不再更新給使用者的 API 層是否可行;
- 流量調撥,灰階引流,藍綠釋出,AB Test 等新的訴求;
這些困擾着我們,我們知道在 SOA 的架構下,負責每個服務的團隊都可以獨立地去負責一個或者多個服務,這些服務的更新維護也不需要其他的團隊的接入,SOA 其實做到了團隊之間可以按照接口的契約來接耦。但是長期以來,基礎設施團隊需要推動很多事情,都需要業務團隊進行緊密的配合,幫忙更新 JAR 包,基礎設施團隊和業務團隊在工作上的耦合非常嚴重,上面提到的各種問題,包括線上用戶端版本的不一緻,更新成本高等等,都是這個問題帶來的後果。
而 Service Mesh 提供了一種可能性,能夠将基礎設施下沉,讓基礎設施團隊和業務團隊能夠解耦,讓基礎設施和業務都可以更加快步地往前跑。
我們的方案
說了這麼多,那我們怎麼解決呢?
方案一:全部遷移到 Envoy?不現實,自有協定+曆史負擔。
方案二:透明劫持?性能問題,且表達能力有限,運維和可監控性,風險不太可控。
方案三:自研資料面,最終我們給出的答案是 SOFAMosn。
總體
我們的 SOFAMosn 支援了 Pilot ,自有服務發現
SOFARegistry,和自有的消息元件,還有一些 DB 的元件。在産品層,提供給開發者,不同的能力,包括運維,監控,安全等能力,這個是目前我們的一個線上的狀态。
SOFARegistry 是螞蟻金服開源的具有承載海量服務注冊和訂閱能力的、高可用的服務注冊中心,在支付寶/螞蟻金服的業務發展驅動下,近十年間已經演進至第五代。
看上去很美好,要走到這個狀态,我們要回答三個問題。
這三個問題後面,分别對應着業務的幾大訴求,大家做過基礎架構的應該比較有感觸。
架構更新方案
準備開始更新之後,我們要分析目前我們的線上情況,而我們現線上上的情況,應用代碼和架構有一定程度的解耦,使用者面向的是一個 API,最終代碼會被打包,在 SOFABoot 中運作起來。
SOFABoot 是螞蟻金服開源的基于 SpringBoot 的研發架構,它在 SpringBoot 的基礎上,提供了諸如 Readiness Check,類隔離,日志空間隔離等能力。在增強了 SpringBoot 的同時,SOFABoot 提供了讓使用者可以在 SpringBoot 中非常友善地使用 SOFA 中間件的能力。
那麼,我們就可以在風險評估可控的情況下,直接更新底層的 SOFABoot,在這裡,我們的 RPC 會檢測一些資訊,來确定目前 Pod 是否需要開啟 SOFAMosn 的能力。然後我們完成如下的步驟。
這裡,我們通過檢測 PaaS 傳遞的容器辨別,知道自己是否開啟了 SOFAMosn,則将釋出和訂閱給 SOFAMosn,然後調用不再尋址,直接完成調用。
可以看到,我們通過批量的運維操作,直接修改了線上的 SOFABoot 版本,以此,來直接使得現有的應用具備了 SOFAMosn 的能力,有些同學可能會問,那你一直這麼做不行嗎?不行,因為這個操作時要配合流量關閉等操作來運作的,也不具備平滑更新的能力。而且直接和業務代碼強相關。不适合長期操作。
這裡我們來詳細回答一下,為什麼不采用社群的流量劫持方案?
主要的原因是一方面 iptables 在規則配置較多時,性能下滑嚴重。另一個更為重要的方面是它的管控性和可觀測性不好,出了問題比較難排查。而 Service Mesh 從初期就把螞蟻金服現線上上的系統全量切換 Mesh 作為目标,并不是隻是跑跑 demo,是以我們對性能和運維的要求是非常高的,畢竟,技術架構更新,如果是以業務有損或者資源使用率大幅度上升,這是無論如何都不能接受的。
容器替換方案
解決了剛剛提到的第一個難題,也隻是解決了可以做,而并不能做得好,更沒有做得快,面對線上數十萬,帶着流量的業務容器, 我們如何立刻開始實作這些容器的快速穩定接入?
這麼大的量,按照傳統的替換接入顯然是很耗接入成本的事情,于是我們選擇了原地接入,我們可以來看下兩者的差別
在之前,我們做一些更新操作之類的,都是需要有一定的資源 Buffer,然後批量的進行操作,替換 Buffer 的不斷移動,來完成更新的操作。這就要求 PaaS 層留有非常多的 Buffer,但是在 雙11 的情況下,我們要求不增加機器,并且為了一個接入 SOFAMosn 的操作,反而需要更多的錢來買資源,這豈不是背離了我們的初衷。有人可能會問,不是還是增加了記憶體和 CPU 嗎,這是提高了 CPU 使用率。以前業務的 CPU 使用率很低。并且這個是一個類似超賣的方案。看上去配置設定了。實際上基本沒增加。
可以看到, 通過 Paas 層,我們的 Operator 操作,直接在現有容器中注入,并原地重新開機,在容器級别完成更新。更新完成後,這個 Pod 就具備了 SOFAMosn 的能力。
SOFAMosn 更新方案
在快速接入的問題完成後,我們要面臨第二個問題,由于是大規模的容器,是以 SOFAMosn 在開發過程中,勢必會存在一些問題,出現問題,如何更新,要知道,線上幾十萬容器要更新一個元件的難度是很大的,是以,在版本初期,我們就考慮到 SOFAMosn 更新的方案。
能想到的最簡單的方法,就是銷毀容器,然後用新的來重建,但是在容器數量很多的時候,這種運維成本是不可接受的。如果銷毀容器重建的速度不夠快,就可能會影響業務的容量,造成業務故障。是以,我們在 SOFAMosn 層面,和 PaaS 一起,開發了無損流量更新的方案。
在這個方案中。SOFAMosn 會感覺自己的狀态,新的 SOFAMosn 啟動會通過共享卷的 Domain Socket 來檢測是否已有老的 SOFAMosn 在運作,如果有,則通知原有 SOFAMosn 進行平滑更新操作。
具體來說,SOFAMosn 啟動的時候檢視同 Pod 是否有運作的 SOFAMosn (通過共享卷的domain socket),如果存在,需要進入如下流程:
1.New Mosn 通知 Old Mosn,進入平滑更新流程
2.Old Mosn 把服務的 Listen Fd 傳遞給 New Mosn,New Mosn 接收 Fd 之後啟動, 此時 Old 和 New Mosn 都正常提供服務。
3.然後 New Mosn 通知 Old Mosn,關閉 Listen Fd,然後開始遷移存量的長連結。
4.Old Mosn 遷移完成, 銷毀容器。
這樣,我們就能做到,線上做任意的 SOFAMosn 版本更新,而不影響老的業務,這個過程中的技術細節,不做過多介紹,之後,SOFAStack 會有更詳細的分享文章。
分時排程案例
技術的變革通常一定不是技術本身的訴求,一定是業務的訴求,是場景的訴求。沒有人會為了更新而更新,為了革新而革新,通常,技術受業務驅動,也反過來驅動業務。
在阿裡經濟體下,在不斷的淘寶直播,實時紅包,螞蟻森林,各種活動的不斷擴張中,給技術帶了複雜了場景考驗。
這個時候,業務同學往往想的是什麼?我的量快撐不住了,我的代碼已經最優化了,我要擴容加機器,而更多的機器付出更多的成本,面對這樣的情況,我們覺得應用 Service Mesh,是一個很好的解法。通過和 JVM, 系統部的配合,利用進階的分時排程實作靈活的資源排程,不加機器。這個可以在資源排程下有更好的效果。
首先,我們假設有兩個大的資源池的資源需求情況,可以看到在 X 點的時候,資源域 A 需要更多的資源,Y 點的時候,資源域 B 需要更多的資源,總量不得增加。那當然,我們就希望能借調機器。就像下面這樣。
請大家看左圖。
在這個方案中, 我們需要先釋放資源,然後銷毀程序,然後開始重建資源,然後啟動資源域 B 的資源。這個過程對于大量的機器,是很重的,而且變更就是風險,關鍵時候,做這種變更,很有可能帶來衍生影響。
而在 SOFAMosn 中,我們有了新的解法。如右圖所示,有一部分資源,一直通過超賣,運作着兩種應用,但是 X 點的時候,對于資源域 A,我們通過 SOFAMosn 來将流量全部轉走,這樣,應用的 CPU 和記憶體就被限制到非常低的情況,大概保留 1% 的能力。這樣,機器依然可以預熱,程序也不停。
在這裡。我們可以看這張圖。
當需要比較大的資源排程的時候,我們推送一把開關,則資源限制打開,包活狀态取消。資源域 B 瞬間可以滿血複活。而資源域 A 此時進入上一個狀态,CPU 和記憶體被限制。在這裡,SOFAMosn 以一個極低的資源占用。完成流量保活的能力。使得資源的快速借調成為可能。
我們對 Service Mesh 的思考與未來
Service Mesh 在螞蟻金服經過 2 年的沉澱,最終經過 雙11 的檢驗,在 雙11 ,我們覆寫了 200+ 的 雙11 交易核心鍊路,Mosn 注入的容器數量達到了數十萬,雙11 當天處理的 QPS 達到了幾千萬,平均處理 RT<0.2 ms,SOFAMosn 本身在大促中間完成了數十次的線上更新,基本上達到了我們的預期,初步完成了基礎設施和業務的第一步的分離,見證了 Mesh 化之後基礎設施的疊代速度。
不論何種架構,軟體工程沒有銀彈。架構設計與方案落地總是一種平衡與取舍,目前還有一些 Gap 需要我們繼續努力,但是我們相信,雲原生是遠方也是未來,經過我們兩年的探索和實踐,我們也積累了豐富的經驗。
我們相信,Service Mesh 可能會是雲原生下最接近“銀彈”的那一顆,未來 Service Mesh 會成為雲原生下微服務的标準解決方案,接下來螞蟻金服将和阿裡集團一起深度參與到 Istio 社群中去,與社群一起把 Istio 打造成 Service Mesh 的事實标準。
本書亮點
- 雙11 超大規模 K8s 叢集實踐中,遇到的問題及解決方法詳述
- 雲原生化最佳組合:Kubernetes+容器+神龍,實作核心系統 100% 上雲的技術細節
- 雙 11 Service Mesh 超大規模落地解決方案
“ 關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術圈。”