百度在 Service Mesh 上的大規模落地實踐
4 月 15 日-16 日,由 InfoQ 主辦的 DIVE 全球基礎軟體創新大會 通過雲上展廳的形式成功召開。在 微服務 & 服務治理專場 ,來自百度的資深研發工程師劉超帶來了主題為《百度在 Service Mesh 上的大規模落地實踐》的演講,以下為主要內容。服務網格作為近幾年來雲原生領域的熱門話題,一直受到大家的關注。百度作為一家大型的商業化網際網路公司,也一直在服務網格領域進行探索,並積累了大量的生產級別的最佳實踐。
本次分享,我將和大家分享以下三部分內容:服務網格簡介、百度在服務網格的最佳實踐、對服務網格的未來規劃與展望。
什麼是服務網格?
基於 SDK/服務框架的微服務治理體系
從傳統單體應用到微服務架構轉變去落地時,基於 SDK 和服務框架這種微服務治理體系,這種傳統的服務治理能力完全是由 SDK 以及服務框架來實現的。這其中,包含了很多服務治理、服務發現、服務路由、服務重試、熔斷限流等微服務相關的一些能力。業務程式重度依賴 SDK 及其服務框架,並和語言、業務繫結在一起。
基於這樣一個服務框架的服務治理體系,在由傳統的單體到微服務的轉變之後,將面臨著很多種挑戰:
具體來說,在語言繫結層面,傳統的微服務治理體系可能要跟具體的語言繫結,因為它跟具體的業務邏輯是要繫結在一起的。
從整體來看,在多語言層面很難做到一個統一的技術,因為語言本身有各自的特性,還有各個語言的能力,都有不太一樣的情況。
此外,採用傳統的 SDK,在向前去演進的時候,很難去推動業務去做升級,SDK 和業務嚴重綁定了,這樣會造成演進困難。
基於透明代理的服務治理體系
基於這些問題,我們將非業務邏輯相關的微服務治理,放在另外一個透明代理,即一個輕量級的網格代理,我們稱它為 sidecar。在 sidecar 層面,我們做了很多的服務發現、負載均衡、服務路由等等。
這樣服務的概念更加純粹,不同的服務和微服務進來,只需要關心自己的業務邏輯實現就可以了,完全把這種非業務的實現邏輯,放在 sidecar 層面去做。
這種典型場景具備四個特點:它本身和業務無關,真正做到了從業務中剝離出來;由於它和業務在兩個獨立的程序裡,所以不存在語言繫結的情況;它和業務邏輯沒有強烈的耦合,獨立演進,包括獨立的升級和維護;透明升級的,就是我們基於 sidecar 這樣一個能力的升級是不再依託於業務的升級,因為本身沒有繫結,這是我們基於透明代理的服務治理體系。
Istio 架構
這種基於透明代理的服務治理體系,可以簡單稱它為服務網格。我們先看一下其典型代表 Istio,Istio 是一個在服務網格領域深受大家喜愛,也深受開發者追捧的框架架構。
我們來看一下它的典型架構。

Service A 和 Service B 是我們的兩個業務應用,Envoy Proxy 就是一個透明代理,它本身對業務是透明的。我們可以看到,有一個控制平面 Istio control plane,控制平面可以簡單理解為,它會向著我們所有的 sidecar 去推送整體的一些配置、資料等等。通過這樣一個典型的 Istio 架構,來引出我們這個服務網格的概念。
從整體視角上來看,所有的 sidecar 都是在一個網狀結構裡進行透明的流量轉發和治理,組成了一個扁平的網狀,這種由透明代理組成的一個網狀結構,我們可以稱它為服務網格,服務網格本身是基於透明代理去實現的。
百度服務網格最佳實踐
接下來,我和大家分享下百度服務網格最佳實踐,主要介紹服務網格在百度的整體實踐,包括我們怎麼去落地服務網格,以及帶來的業務收益。
百度雲原生髮展歷程

百度在雲原生領域的發展歷程還是比較早的,我們在 2012 年到 2013 年,內部就有很多這種容器平臺,比如 Matrix。在 2013 到 2015 年,我們內部有很多業務線逐步地去落地和推廣雲原生理念。在 2013 年到 2017 年,我們有大量的品牌業務、廣告業務、營銷業務開始使用了微服務引擎,其中比較典型的是我們的 BFE,以及百度 RPC(brpc)。
2015 年到 2018 年,我們整體的業務線,包括文庫、音樂、人工智慧等等,也開始在開源的 Kubernetes 裡去做一些實踐,大概有幾十萬的容器使用了 Kubernetes 技術。在 2018 到 2019 年,我們整體做了很多的微服務化、應用平臺、PaaS 平臺,其中也包含了我們對 Springcloud 和 Service Mesh(服務網格)的探索。
2019 到 2022 年,我們在百度的地圖和資訊流裡進行了服務網格的大規模落地,在服務網格這部分做了很多事情,產生了很大的價值收益,後面我們會逐個去介紹。
百度核心業務微服務現狀

在業務線上,我們有很多核心業務線,比如百度 APP、資訊流、地圖,還有百度小程式。百度也有很多開發語言,比如 C++、Golang、PHP、Java 等等,形成了一個多語言的場景。在開發框架裡,基於傳統的微服務框架,我們也有很多內部實現的積累,比較有名的是 BRPC 框架,還有 Golang 的 GDP,PHP 的 ODP 都有一些實踐,並且跟業界開源的 SpringCloud 也有一些落地實踐。
在通訊協議方面,因為百度很多核心商業對效能有很高的要求,我們在大量的私有協議裡有很多擴充套件,其中有大量的 L4 層協議。通過這樣一個方式,百度的很多業務線已經完成了微服務的改造,它可能還是停留在傳統的服務框架和 SDK 這樣一個模式,形成了一個多開發語言、多框架和多通訊協議的複雜的異構系統。
基於傳統的服務框架的模式,本身已經不能夠再滿足像百度這樣體量的商業化系統的演進過程,同時也不再具備滿足更高的服務治理的要求。基於這樣一個背景,我們探索了服務網格的落地。
服務網格落地挑戰和困難
我們在落地服務網格時,有很多挑戰和困難。
第一個比較典型的困難就是應用的型別比較多,因為日積月累,有大量商業化的服務框架應用涉及到服務網格的遷移。第二,像百度這種商業化體系,本身對時延等要求比較高。第三,我們對服務治理的需求比較多,在使用者側,當一個新的服務網格技術去落地時,使用者也是比較希望這個全新的技術能夠解決他在場景化的一些問題。最後就是技術理念的問題,因為服務網格是一個比較新的技術概念和理念,它涉及到的技術領域比較複雜,本身理念也比較新,開發者還是有一些接受的過程。
百度服務網格實踐過程與大規模落地步驟
百度已經形成了很多微服務技術框架和架構,我們要去做一個新技術的推廣,包括服務網格的落地,首先要去傾聽業務的訴求。基於這些業務訴求,選擇一些比較典型的核心業務,然後逐步向服務網格這樣一個全新的微服務架構去轉型。最後我們實現了比較大規模的業務落地,包括我們在大規模場景下一些穩定性相關的保障。

接下來,我們看一下百度服務網格大規模落地的步驟。

首先,我們需要解決流量接入的問題,流量怎麼劫持到 sidecar,去做流量攔截和流量的治理。第二,解決對自有協議的相容問題。百度有很多私有協議,要在 sidecar 層面去支撐我們所有的私有協議,最後要對老框架、老協議去做一些相容。
解決完接入問題之後,再來看效能部分。因為我們是一個大規模的商業化場景,我們要重點解決剛才提到的 sidecar 的效能優化,還有控制面的效能優化,以及我們在整體代理架構的簡化。
最後,業務接入服務網格之後,我們要來看一下這個服務網格最終有什麼樣的業務收益。我們在高階能力的策略還是比較豐富的,能夠有效的保證業務的穩定性,同時在一些網格的特性,包括故障注入、容量探測、自動止損等方面也做了增強,同時對服務的可觀測性也做了一些彌補和增強。
服務網格效能優化
代理架構簡化
接下來看下在代理架構簡化這一層面,我們主要做了哪些事情。

先來看一下社群的方案。社群的方案是一個典型的雙跳方案,每個業務程式都有一個邊車,所有的流量都要經過兩次邊車處理,它有一個兩倍的延時,包括兩倍的資源開銷。
我們對此做了一定的優化。我們提供了 client-side 這樣一個模式,和社群的方案對比來看,業務之間在通訊的時候,業務本身不再依託於邊車的流量管理,也就是說,我們相當於僅增加一倍的延遲,而不是社群的兩倍延遲。同時在資源效能開銷方面又降低了很多,這是因為我們發現大部分的服務治理的能力是可以在客戶端來實現的。
控制面優化
在控制面優化上,我們整體是基於資料面加控制面的模式來做的。
第一步,利用框架的一些能力,採集服務的呼叫關係,把資料同步給我們的控制平面,控制平面會把服務所需的資料向邊車去下發,達到一個按需下發的能力。同時,我們的邊車也是主動地向對應的註冊中心,查詢獲取到它的服務治理的能力。
在優化控制面的效能之後,我們也在服務網格的效能方面做了一些優化,包括控制面和資料面做了一些融合。我們引入了 BRPC 做了很多這種優化,因為在百度內部有很多 BRPC 的場景,同時我們也結合了 BRPC 和 Envoy 的一些優勢,基於 Envoy 靈活的 filter 機制,做了豐富的策略,支援動態的 XDS 機制,同時也結合了 BRPC 的高效能的執行緒技術、Buffer 庫、優秀的 IO 機制,最終達到的效果。
最終在 CPU 和平均延時這兩個比較核心的指標層面,有很強的效能提升。
支援異構微服務應用互訪
我們在探尋的時候發現,傳統的業務邏輯加 SDK 的微服務架構,和應用加 sidecar 這樣一個全新的 Service Mesh 架構,是有一個過渡態的。在這個過渡態裡,我們需要異構應用的互訪,也就是說,傳統的微服務應用能夠和我們這個 Service Mesh 的應用去做互通,Service Mesh 裡面的應用程式,同樣要去和這種傳統的異構程式去互通,我們稱它為過渡態。這是我們典型的一個應用場景,也是業務線比較關心的一個問題。

Fallback 機制支援流量一鍵回退
另外我們做了一個 Fallback 機制支援流量的一鍵回退。剛才提到,在典型的 Service Mesh 架構裡,這種代理模式是比較好理解的,就是所有的請求都會經過 sidecar。這是一個典型的 Service Mesh 架構,我們可以稱它為一個典型的代理模式。
另外一個方式,我們稱它為直連模式,就是這個請求不再經過 sidecar 攔截,直接寫入業務程序,和業務程序直接去通訊,這個就是我們典型的這種業務之間通訊方式。
業務在向這種典型的 Service Mesh 架構去遷移或者轉變的時候,有個擔心點是,傳統的業務可能採用直連模式,換成這種代理模式之後,因為所有的流量都會經過 sidecar 攔截,一方面會增加時延,以及對穩定性的訴求;另外一方面,在極端的情況下,如果 sidecar 資料平面產生了一些故障,怎麼快速幫業務止損。
我們基於定製化的一些能力,做了 Fallback 機制。Fallback 機制提供了一個產品化的能力,能夠自由地在代理模式和直聯模式間去靈活切換。這樣,一個典型的應用場景就是在故障或者是業務止損方面,如果傳統的 Service Mesh 架構發生了一些故障,我們能夠快速地把流量切回到直聯模式,這是我們在穩定性方面的一個保障,也是給業務信心的增強。
零改造、業務平滑遷移服務網格
在針對一些傳統的 Java 的微服務應用程式考量時,會發現一些傳統的微服務應用已經有一些現有的微服務治理體系,那麼,我們怎麼去讓它做這種服務網格的遷移?
我們採用了一種無侵入的實現方式,利用了 JavaAgent 這樣一個技術,首先它能夠做到對業務無侵入,因為它本身是基於位元組碼層面的一些修改。基於這些能力,我們實現了它在服務網格里面的服務治理的能力。
第一個比較典型的場景就是我們能夠動態地開啟和關閉傳統微服務治理框架的治理能力,因為在傳統的框架裡面,它本身已經有了微服務的能力,在接入了服務網格之後,我們希望它和服務網格的基本能力能夠做一個取捨,而不是一個相互疊加。
第二,可能熟悉服務網格的同學都對這點深有體會,雖然服務網格是由 sidecar 來代理流量的,但它本身需要在業務進行微服務監控的時候,能夠主動地把 sidecar 產生的對應的 trace 資訊做一些透穿。這部分,我們也是利用探針的能力,去實現了微服務呼叫關係的 trace 資訊的透穿。
第三,我們也做了一些增強。我們發現,Istio 這樣全量推送的架構裡,可能會有一些效能的損失,我們會主動探測到應用程式裡邊需要訪問的微服務呼叫關係,基於這個呼叫關係,我們把這些元資料做一些收集,再同步到我們的控制面,再到我們的 sidecar 層面去生效,這樣保證我們在大規模場景下的效能優勢。
提升 Service Mesh 效能
接下來介紹下我們內部在提升 Service Mesh 效能方面的一些實踐,典型實踐就是 Service Mesh 的單跳方案。

Service Mesh 單跳方案主要是解決 sidecar 的非必要攔截。社群的雙跳方案,業務請求先到某一個服務 A,服務 A 的 Sidecar 進行一個攔截,這個 sidecar 會把請求轉發給服務 A ,同時服務 A 要向服務 B 發起請求,對外的請求也要過一次 sidecar。同樣的,服務 B 的 sidecar 也要把這個請求再轉發到服務 B,再出去的時候,再過 sidecar,我們看到這樣的話,每次請求進出服務 A 和服務 B 都會產生這個 sidecar 的攔截。
我們發現,大多數服務治理的策略往往可以在服務 A,也就是 client 端來實現。基於此,我們做了一個單跳的方案。我們在入向和出向的時候,只有在第一次請求拿到服務 A,往出走的時候,我們再過服務 A 的 sidecar,同時在訪問服務 B 的時候,我們這個請求是不需要再過服務 B 的 sidecar。基於這樣的一個方案,我們節省了一部分 sidecar 的資源開銷,還有時延的開銷。
大規模應用場景
接下來,我們再來看一下一些內部的典型大規模應用場景。

在按需下發方面,我們的 XDS 只下發必需的資料。我們在控制面和資料面之間互動的時候,控制面因為往往不知道資料面需要哪些服務,它是一個全量下發的邏輯。舉一個典型的例子,如果 Kubernetes 叢集裡有十個服務,我們的控制面 list watch 十個服務之後,就會把這十個服務的資訊全量推給 sidecar,sidecar 接管業務可能只訪問這十個服務裡面的一兩個,這樣的話,就會造成了資料冗餘。
在這樣一個場景裡,我們做了一些事情,就是 XDS 在推送的時候,我們只下發必要的資料。這樣的話,我們在十條資料裡面,只精準地把一條資料或者兩條 sidecar 所需要的資料推下去,sidecar 就能夠主動地把資料加到自己執行的記憶體裡面去執行,顯著減小 Envoy 的效能損耗。
另外,我們還有個架構升級,做了 XDS 的優化,EDS 從推送模式改為主動模式。資料面和控制面之間通訊的時候,完全是由控制面向資料面去進行資料的推送,但是我們發現在量比較大的時候,是有一定的效能損失和時延過長問題,因此在這部分,我們做了一些效能優化。
我們還對接了很多註冊中心,包括 Consul、Eureka、Zookeeper,存量業務可能使用了多種註冊中心,在向服務網格去遷移的時候,我們需要對接這些註冊中心。
業務無感接入 Service Mesh 可觀測
典型的 Service Mesh 接入過程中,本身是需要透穿 sidecar 所傳遞的 Trace 資訊的,因為我們所有的進出流量都被 sidecar 所攔截,並且產生一個 Span ID 和一個 Trace ID。很多業務有些排斥,或者存在抵抗心理,因為他不太清楚業務為什麼接入網格,本身是一個無侵入的方案,為什麼要做這種 Trace 相關資訊的透穿。
我們針對大量的存量 Java 業務,提供了一種 Java 無感知的接入方式,也是整體的基於 Java agent 技術來做的。所有的請求到達業務之後,利用 JavaAgent 做一個 Trace 資訊的儲存,業務往外發請求的時候,我們會把這個儲存裡面的元資料資訊拿到,也就是剛才提到的這個 Trace ID 和 Span ID,達到業務無侵入、無感知的接入方式。
另外,因為傳統的業務可能它本身也有自己的監控體系,可能還要監控自己這次請求經過了哪些方法、哪些函式的處理過程。因為在 Sidecar 或者是服務網格這樣一個典型的架構裡,所有的監控資料都是在 Sidecar 這一側,也就是在資料面一側去產生的,它對於內部業務程式的執行過程,確實不具備優勢。而對於業務的內部的一些執行過程,往往可能還是業務比較關心的,比如哪個方法執行地比較慢,哪個方法出錯了。
所以,在對一些業務監控時,往往通過業務引入對應的監控 SDK,然後去做打點,然後再彙報給監控系統。其實我們對於 Java 業務,也是利用 JavaAgent 的這種採集技術,把業務裡面基於方法級別的具體實現過程,做了採集和彙報,同時,和 Sidecar 產生的 Trace 資訊以及 Span 資訊做一個連線。
這樣的話,其實我們接入到網格之後的 Trace 體系跟業務原生的這種已有的 Trace 體系,基本上是打平的,從業務的真正的請求到 Sidecar,然後到業務真正的內部執行過程,然後到業務再向另外的伺服器發起請求的時候,然後再經過 Sidecar,以及這樣一個 Trace 的過程。
同時,我們也支援了很多元件,比如 Spring、Kafka、Redis 這樣一些體系。我們把資料採集到之後,其實是要做一些儲存和對接的,因為現在整體業界對於監控系統的支援還是比較多的,比較有名的包括 Jaeger,或者 Skywalking 等等。
本身基於 Service Mesh 這樣一些架構,其實產生了很多資料,服務網格和 Service Mesh 把這些資料採集到之後,會把這些資料向外去傳送。我們剛才提到外面的監控系統有很多,每一種監控系統可能都是不同的資料結構,所以我們在這塊利用了 OpenTelemetry,能夠把所有的基於業務和 Sidecar 產生的 Trace 資訊和 Span 資訊,向所有的 collector 去傳送。
我們可以認為 collector 是一個標準,我們的 Sidecar 和業務產生的資料只滿足這樣一個標準就可以了,然後我們把所有的資料發給 OpenTelemetry。OpenTelemetry 更像一箇中間代理,由它來遮蔽資料儲存和監控體系的資料的差異性。
我們剛才提到了所有的資料都和 OpenTelemetr 做了一個數據的約束,由 OpenTelemetry 把資料進行一些轉換和轉變,轉換成不同的這種監控體系所需要的這種資料格式,把這個資料再發送到不同的監控體系。避免我們後期頻繁地變化這個監控體系之後,可能會對我們的資料格式產生一定影響。
百度服務網格落地規模和收益
接下來分享下百度服務網格的落地規模和收益。我們在核心的業務線包含手機百度、Feed、百度地圖、小程式、好看視訊,都有非常大規模的落地,也是我們比較典型的一個商業化場景。
收益方面,第一個比較典型的收益就是我們在跨語言層面真正地做到了統一的服務治理,因為服務網格是一個典型的基礎服務治理能力和業務邏輯解綁的架構,真正地能夠實現跨語言的統一服務治理。
另外,在服務的可用性方面,也做了很多的增強和提升,同時與典型的服務治理週期相比,我們實現由月級到分鐘級別大幅度的降低,業務對於我們這種服務治理的有非常大的體驗感的增強。最後,我們在基礎設施層面能夠統一技術棧,這是我們從業務側和技術架構側去歸納的收益。
規模方面,我們的例項有 10 萬多個,真正地落地了我們的服務網格全新微服務架構。在處理流量方面,我們在核心的商業體系和商業系統有大量的線上流量都經過了服務網格,我們的服務網格也經受住了百億級別的流量考驗。
未來規劃與展望
eBPF 增強 Service Mesh
未來,我們還有很多增強點去做,比較典型的就是 eBPF 增強 Service Mesh。我們剛才提到在社群的方案裡,有基於 iptables 的一些實現機制。我們發現其實基於 iptables 的話,它會帶來一些效能損耗,包括頻繁地在使用者態和核心態去做這種切換,是有一些效能的損失和延遲的。
所以,我們未來在 eBPF 層面需要做很多增強。我們希望在核心態能夠儘快地加速流量的轉發,不再經過多次 Socket 的機制,儘快地把這流量傳達給資料平面,從而節省服務到資料平面的延遲,給使用者的感受也是更好的。
提升業務接入 Service Mesh 體驗
此前提到,社群是一個全量推送的方案。舉個例子,我們有十個服務,也就是 Kubernetes 有十個 Kubernetes Service,那我們這個控制平面很有可能把這十個服務去全量推送,這樣帶來的一個問題就是 Envoy 的資料配置項,還有配置的資料都是比較冗餘的。
基於這樣的方式,社群提供了一種手動配置的方式,主要是基於 Sidecar CRD 的模式,讓使用者手動地在 Sidecar 層面來約束服務的呼叫關係。這樣其實對使用者的接入體驗不是很好,因為往往使用者可能不太清楚自己這個服務的呼叫關係。
因此,我們要做自動地按需下發。避免使用者手動地去配置 Sidecar CRD,通過一些其他的流量管理方式來收集業務的呼叫關係,讓使用者真正地體會到業務的無感介入。讓我們通過一些技術的手段,收集到這個服務之間這種呼叫關係,然後快速地提升業務的接入體驗。這樣,我們能夠減少配置的非必要資料,提升服務網格的整體效能。
另外,百度其實在雲原生服務網格做了很多的積累。在內部,包括核心的商業性也做了很多的生產級別的服務網格論證,我們準備去賦能業界,提供百度的服務網格產品。
可以看到,服務網格本身是有很多能力的,比如服務治理、服務監控,還有可靠的安全傳輸。真正去落地的時候,可能還要涉及到 Sidecar 效能的提升,還有運維側,以及良好的可擴充套件性,包括我們在傳統虛機的一些接入,這些都是我們都是要考量的。
另外,在視覺化方面其實也有一些訴求的。業務在接入的時候,可能會有一些場景化的訴求,比如真正地接入了 mesh 它能帶來的價值或收益,或者是能在什麼樣的一些場景裡面帶來業務的落地。
在周邊生態,除了有 Istio、Envoy、Jaeger、OpenTelemetry、Prometheus,可以看到它是非常龐大的一個雲原生體系,基於這樣一個雲原生技術棧,我們發現一家公司要去落地的話,挑戰也是比較大的。百度可以提供這種開箱即用的服務和產品,能夠讓業界的客戶快速地使用,同時,針對一些業界的使用場景來提供使用者友好的控制檯,並對開發者友好。
經過了百度生產級別的驗證,以及核心級別的流量的考證,我們也相信這個產品給廣大開發者能夠帶來真真正正的業務收益,這也是我們百度在服務網格和雲原生的一個多年的沉澱,也歡迎大家來持續關注。
- 那些 Go 語言發展歷史上的重大決策
- 從趨勢到挑戰,一站式解讀作業系統運維和可觀測性
- 百萬級 Topic,騰訊雲的 Apache Pulsar 穩定性實踐
- Apache Doris 在思必馳的應用優化實踐:海量語音通話資料下,實時、離線一體的數倉架構設計實踐
- 愛數正式開源認知智慧開發框架 KWeaver
- 運維智慧化的三大關鍵技術
- “抄我的還‘反捅’我一刀”,Gary Marcus 發文駁斥圖靈獎得主 Yann LeCun
- 當出海成為必選項,企業如何構建全場景全生態技術底座?
- 數智底座必備能力三:快速構建創新應用
- Docker 多階段構建實戰 (multi-stage builds)
- 工作筆記之 SELECT 語句在 SAP ABAP 中的用法總結(上)
- 經久不衰的設計定律是不要讓我思考的設計
- 不要指望下一個像 GPT 這樣的大型語言模型會民主化
- Java 近期新聞:Helidon Níma、Spring Framework、MicroProfile、MicroStream、Kotlin 和 Piranha
- 一文入門 jQuery
- C 學習 ---__libc_open 函式的原理
- 監控系統工作原理
- 甲骨文新微服務框架 Helidon Níma:使用虛擬執行緒實現高效能
- 【雲原生 | 從零開始學 Kubernetes】二、使用 kubeadm 搭建 K8S 叢集
- Elasticsearch 聚合學習之四:結果排序