本期與大家共同探討微服務當下最新的框架 —— ServiceMesh 。
微服務框架
微服務,簡單而言,就是將原有的一個整體的應用,拆成多個細粒度的小應用,同時具備分布式的特點。化整為零后當然會帶來一系列的問題,就好比一個開小賣鋪的后來開成了連鎖店一樣,一定會帶來很多跟進貨、賣貨沒關系的問題。那么微服務帶來的這一系列問題,就需要通過微服務框架來解決。
通常狹義的“微服務”僅指的是 SpringCloud、Dubbo 這一類的傳統微服務框架,也是國內使用較多的開源微服務框架。另外一類新型的微服務框架就是服務網格(ServiceMesh),也在近兩年逐漸變得熱門,比如 Linkerd、Consul、Istio 等都屬於服務網格的框架。
ServiceMesh的特點
做微服務首要解決的問題是通信問題:服務尋址、訪問控制、流量限流、熔斷降級等等,都是通信上的問題,而微服務、服務網格的框架就是用來解決這類問題的。但是在解決的方式上,傳統的微服務框架、新型的服務網格框架則有所不同,而且是大有不同。兩者之間的區別我們可以看一下這個圖:

傳統微服務框架以 SpringCloud 為例,開發的時候需要引入 SpringCloud 相關的所有依賴,也就是將通信部分包到了引入的依賴(SDK)里,當然這也考驗開發人員的能力,需要開發人員熟悉 SpringCloud 框架才能用,並且目前只支持 Java 語言。服務網格類的框架,說來也簡單,就是把上面的 SDK 拿出來,單獨運行,只要能實現該 SDK 的功能,目的也就達到了,而抽出來單獨運行的 SDK 稱之為 Sidecar,在服務網格的管理中屬於數據面的管理。
當然 Sidecar 也有一系列需要解決的問題,比如 Sidecar 要全權代理其通信,即流量劫持;服務發現、服務健康檢測要有相應的機制;策略下發和統一管理也都需要考慮。在服務網格的管理中屬於控制面的管理。
與傳統微服務框架相比,服務網格確實是有很多優勢。服務的業務與通信拆成兩個部分,業務開發人員不用關心微服務框架、微服務治理的事情,開發的時候也不會涉及框架的學習,甚至不用關心使用哪種開發語言;運維管理組或者架構組,也不用擔心自己在通信架構上的優化,很難升級到運行中的系統上。用專業的術語來說就是將業務與治理解耦,微服務治理能力下沉至運維層,降低開發難度,在架構上更容易實現層次化、規范化、體系化。
性能是不是服務網絡最大的挑戰?
我們知道當單體應用拆分成微服務以后,本來進程內的調用卻變成了網絡間的調用,性能自然是不如從前。那么同樣的道理,現在是將每個微服務又拆成了兩個運行的程序,同樣需要通過一個網絡的調用,這豈不是又加重了性能的問題?如果我們把每一次服務間的調用,都比做是搭乘公交車,原本 A 服務調用 B 服務,就好似搭乘了一趟公交,那么帶上 Sidecar 的服務調用就是 A 服務->Sidecar->Sidecar->B 服務,這樣好比是中間換乘了兩次公交,這樣算來延遲可增加不少,幾近於原來的三倍?
其實仔細分析一下會發現,從處理時間上來說,ServiceMesh 其實並沒有增加通信性能的消耗。舉個例子,在沒有引入 ServiceMesh 時,A 服務調用 B 服務,消耗的時間主要是:
● A發出信息之前,首先會經過自身的框架(SDK)做處理,因為傳統的微服務框架基本上都是客戶端負載均衡,所以在這里會過一些負載均衡、算法選址、熔斷降級等治理功能,耗時在1ms左右;
● A->B的網絡通信時間,網絡暢通的情況下,不超過0.1ms;
● B接收到數據后,也首先是框架(SDK)處理,比如訪問權限、黑白名單等,姑且叫做治理功能處理,大概也是會消耗1ms;
● 治理相關處理完以后,就是業務處理了,首先是協議編解碼,然后是業務代碼的處理,一個不是很復雜的業務服務處理,應該是在10ms左右。
這樣算下來,A->B的微服務調用,從 A 出口算起到 B 處理完成,粗略的估計是12.1ms,我們再來看A->Sidecar->Sidecar-B的業務處理,大概需要花費的時間:
● A服務發出通信信息,到A服務的 Sidecar 上,這個網絡傳輸的時間一定在0.1ms以內,通常都是主機內的本地調用,因此也不占據網絡資源;
● A服務的 Sidecar 接收信息后,會做類似於之前的 SDK 一樣的處理,也就是熔斷、限流、訪問控制就在這里做好了,處理時間也類似大概1ms。注意服務網格的訪問控制、黑白名單也是在調用端處理的;
● A服務的Sidecar將信息傳輸到B服務 Sidecar ,與傳統微服務的A到B的傳輸相同,傳輸時間也相同,姑且算0.1ms;
● 信息到B服務的 Sidecar 以后,如果不是加密傳輸,那么B服務的 Sidecar 不用做任何處理,因為治理相關的功能已經全部放在了調用端,所以B服務的 Sidecar 直接透傳,幾乎不消耗時間;
● B服務的 Sidecar 將信息傳送到B服務,網絡也按照0.1ms算;
● 最后B服務的協議編解碼、業務處理,也是將近10ms。
統計一下服務網格平均一次調用的消耗大概是11.3ms。延遲的消耗不增反減,這也是前期我們經過很多次的壓測以后發現的一個規律。
意料之外,情理之中
經過上面的性能分析,結果大出我們的意料之外,本以為將近三倍的延時,卻發現幾乎沒有太大變化,這是我們有意抬高 ServiceMesh ,還是其本身架構就是向着性能優化的方向走的呢?
其實了解 Sidecar 的處理機制以后,也就能明白這個意料之外的事情其實並不奇怪。
首先 Sidecar 不是一個服務,不處理報文體中的詳細業務內容,只做轉發。拿到報文頭中的目標信息以后,原報文體不做任何處理,其次在轉發的時候執行負載策略、熔斷限流、路由策略等,然后就是通信信息的記錄,以便於監控、日志等管理。為了實現 API 粒度的管理,比如 API 粒度的訪問控制、熔斷限流,Sidecar 還需要有 URL 的路由策略功能,通過不同的 URL 策略,實現細粒度的 API 或 API 組的治理,這也就是 Sidecar 整體的處理流程。
說到這里,大家有沒有發現 Sidecar 跟一個 API 網關的功能、作用好像差不太多?實際上 Sidecar 就是通過 API 網關來實現的,為每一個微服務實例配置一個 API 網關實例,全權接管其流量和通信,以達到透明化的治理。所以在性能方面,CPU、內存的消耗是必然,而通信延遲上卻並不足為慮。
總結
服務網格從 2010 年就被提出,到 2017、2018 年的時候就普遍受到了技術人員的關注,2020 年也被叫做是服務網格落地的元年。了解了服務網格的原理,也就普遍能被市場所接受了,畢竟核心的技術也就在於 API 網關上,而 API 網關又是一個已經完全成熟的一個技術。所以如果現在做微服務化的轉型,ServiceMesh 也是值得考慮的一種技術規范。
在接下來的文章中,我們會將 API 網關、Mesh、Sidecar 做一個統一的介紹和對比,敬請期待~