无责任畅想:云原生中间件的下一站
作者 | 于雨
來源|阿里巴巴云原生公眾號
本文源自 2020 年 12 月 20?日作者在云原生社區 meetup 第二期北京站演講?《Apache Dubbo-go 在云原生時代的實踐與探索》的部分內容,如果對演講完整內容感興趣請訪問:
https://www.bilibili.com/video/av245840877
自從以 2013 年開源的 docker 為代表的的容器技術和以 2014 年開源的 K8s 為代表的容器編排技術登上舞臺之后,相關技術從業人員從認知和體感上接受,云原生時代真的到來了。
當然也有很多資深技術人員認為,云原生時代要從 2010s 時以 OpenStack 為代表的虛機編排時代開始。當然,也有人說其實云原生技術誕生很早,可以從巨型機時代在巨型機上虛擬出若干小型機開始追溯。
在云原生時代,不變鏡像作為核心技術的 docker 定義了不可變的單服務部署形態,統一了容器編排形態的 k8s 則定義了不變的 service 接口,二者結合定義了服務可依賴的不可變的基礎設施。有了這種完備的不變的基礎設置,就可以定義不可變的中間件新形態 – 云原生中間件。
云原生時代的中間件,包含了不可變的緩存、通信、消息、事件(event) 等基礎通信設施,應用只需通過本地代理即可調用所需的服務,無需關心服務能力來源。
微服務框架
從最早的單體應用時代到分布式技術時代,流行的是微服務技術。微服務時代各大公司都沉淀出了具有代表性的一些服務通信框架,如 Google 的 gRPC,阿里的 Dubbo 和 HSF,百度的 bRPC 等等。多個服務通信框架之間的競爭,基本上是在大公司之間進行角力。
站在使用者的角度,當然期待一個網絡框架在進化過程中能夠保持向前兼容性,多個框架之間保持互通性。
1. 服務框架的向后兼容性
通信框架的基礎是通信協議和序列化協議,其中很重要的問題就是新版本協議對舊版本的向后兼容性。在一個組織中一般都使用統一的通信框架,但現實中可能因為各種原因,同一個框架的序列化協議或者通信協議的向后兼容能力差,會導致使用不同版本通信框架的各個服務之間的異構化。如采用了 pb v2 和 pb v3 的通信框架不兼容,不遑多讓的 Thrift 0.8.x 與 Thrift 0.9.x 之間也不兼容。
不過 Protobuf v3 或者 Protobuf v2 的各個子版本之間的向前和先后兼容性還是不錯的,但還是有一些弱雞公司的內部序列化協議無論是否采用 TLV 形式,其協議各個版本的之間還是無法兼容,進而導致各個子版本的服務框架相互異構,最終導致使用了不同版本的服務框架的業務背上大量包袱無法快速演進,有些新版本的業務中存在各種神邏輯可能不是為了兼容舊版本的業務邏輯,而是為了兼容舊版本框架的通信協議。
2. 多框架之間的互通性
一個常識是,組織規模膨脹到足夠大的程度后,不可能有一個通用的框架適用于所有的場景,一些大經濟實體隨著業務體量變大,業務類型變得龐雜,不可避免地存在一些重復的輪子,這些龐大規模的組織因為其規模效應,任何一個適用于特定場景的框架只要能在內部找到若干落地應用場景就足以讓其開發維護成本變得可負擔且收益甚大。
公司內部各個分公司之間可能存在不同服務框架導致各個服務之間通信異構化越來越嚴重,如阿里內部早前存在異構的 Dubbo 和 HSF(目前阿里內部 HSF 和 Dubbo 已經開始融合, HSF 已經采用 Dubbo 作為內核以 Dubbo 插件的形式存在),如當下的阿里的 HSF 和各個收來的新公司之間的網絡通信,其間通信可能不得不借助于 Proxy 形式的通信網關。
每個服務框架各個子版本之間需要保持向后兼容,各個服務框架之間的兼容可能需要網關代理。
3. 多語言框架之間的互聯
除了序列化協議、通信框架的異構外,還普遍存在著因為各個不同語言技術棧之間差異導致的異構:每種語言都有個各自的序列化協議和通信框架。如 Java 世界就存在著 Spring Cloud 和 Dubbo 兩大服務治理框架,Spring Cloud 尚無多語言版本實現,相比之下 Dubbo 的多語言工作稍好一些。
4. 打通打平不同的技術體系
同一實體內部不同公司之間有兩三個不同服務框架的情況已經算是很好了,大公司組織內部可以容忍適量的重復造輪子,但大量的重復造輪子就過猶不及了。據說有巨頭內部不同部門之間存在各自的 RPC 服務框架 ,其總體服務框架超 100+!
隨著國內互聯網行業發展由于頭部效應趨向性明顯,在大魚吃小魚的時代背景下,大公司與收購來的公司之間的技術體系異構也是云原生時代中間件面臨的一個問題,二者之間因為業務規模不同帶來的服務注冊中心、配置中心、語言技術棧、服務鑒權、緩存和存儲等諸多技術不統一。有的剛收來的公司甚至使用了大公司的競爭對手的云平臺,這就又帶來了平臺級的差異,諸如此類的異構問題不一而足。
借助網絡代理技術,可以初步快速打通不同技術體系之間的異構差異。
5. 通信代理的必要性
除了南北向通信的網絡接入層代理外,微服務時代使用同一通信框架的各個服務實體之間直接進行通信,很少聽說各個服務實體之間通過代理 Proxy 進行通信,其根由是各個通信實體之間通信框架同構。
或者說,網絡通信代理被各個強悍的通信框架給消化掉,以 Proxyless SDK 的形式存在,如服務發現、服務路由、容災限流、負載均衡等功能都存在于各個服務框架的 SDK 中。
但隨著多協議多語言等各種因素導致的各個框架之間的各種異化,大家普遍相信:沒有什么差異不是一層 Proxy 解決不了的。
6. Service Mesh
2016 年之后興起的 Service Mesh 技術區分為 Proxy Service Mesh 和 Proxyless Service Mesh,至于二者之間的差異可參見本文 2019 年的一篇文章?Service Mesh 形態芻議。目前比較流行的 Service Mesh 技術形式是 Proxy Service Mesh,其比較有代表性的組件有數據面的 envoy 和控制面的 Istio。
一些 Service Mesh 技術文檔宣稱,將服務框架的序列化協議、通信能力、服務治理能力沉淀到服務網格的代理(如 envoy 這類數據面 sidecar)中,可有如下收益:
- 服務框架 SDK 會變的非常輕量,甚至完全沉淀到 sidecar 中。
- 多語言、多協議和多種通信方式之間的差異將被磨平。
- 統一流量控制,提升系統的彈性。
- 統一監控設施,提高可觀測性。
- 統一安全可信認證,提升安全性。
- 升級過程業務無感,做到平滑升級,提升可靠性。
- 提升業務版本迭代速度。
- 快速打通不同技術治理體系之間的差異。
- 在 Mesh 和 非 Mesh 模式之間快速切換。
有人可能據此誤以為 Service Mesh 技術可將業務和服務框架的復雜性消滅于無形,將 Istio + sidecar 形式為代表的服務網格可以定義為 Service Mesh 的終極形態。
Sidecar 與中間件
Proxy Service Mesh 的數據面的 sidecar 僅具備通信能力,業務應用和 sidecar 之間仍然存在一個 gap:微服務時代應用所使用的中間件系統的能力需要沉淀到 sidecar 中。
1. Sidecar?的能力
Proxy Service Mesh 中 sidecar 的一個典型代表是 envoy,其本質是一個具備通信能力的 local proxy,具備如下數據面能力:
- 流量控制
- 序列化協議轉換
- 通信協議轉換
- 數據路由控制
實際上, envoy 僅僅是提供了這些能力的接口,至于具體的序列化協議轉換、通信協議轉換插件等工作還是需要相關的基礎設施開發人員去做的。
除了序列化協議和通信協議轉換,中間件的其他能力向 Proxy 下沉的過程中,都需要做大量的 envoy filter 層面的工作。相對于 Proxyless 形式的 Service Mesh,Proxy Service Mesh 成本沒有任何變化,其對業務的侵入性也沒有減輕更多。
2. 協議下沉
如果說 Proxyless Service Mesh 形態下的 SDK 升級需要業務層面做很多改造,Proxy Service Mesh 形態下的業務從 Proxyless 向 Proxy 形態升級過程中改造成本也不可謂不小。如果通信協議采用了 Protobuf V3,Proxy Serivce Mesh 形態下的業務升級協議時可能做到平滑升級:只升級 Proxy 不用升級業務服務實體。但現實是一些公司內部的私有協議根本做不到向后兼容,其成本就是升級協議時服務網格的 Proxy 和業務實體一起升級,至于期望的平滑升級就很難做到了。
諸般問題的核心是 Local Proxy 沒有統一通信協議和序列化協議,僅僅注重于流量劫持。
3. 有狀態的應用
Service Mesh 技術的一些愛好者假設服務實體是一個無狀態的服務,其代理也當然是一個無狀態的 sidecar,然后宣傳 Service Mesh 時代的各種紅利。
至于那些有狀態的應用,大公司有人有錢耗費巨量人日成本后,把狀態轉移到 Proxy 中去,讓應用無狀態,但業務無感知的平滑升級是就難做到了。這個成本對大經濟實體來說當然是可負擔且收益甚大的,但不是一些中小廠家所能承受的,他們在踩完各種坑后,可能神奇的發現他們根本沒有實力實現有狀態的 sidecar。
4. 復雜性守恒
總結一番,基于 sidecar 搭建一個 Proxy Service Mesh 可能存在如下工作:
- 不同序列化協議轉換
- 不同通信協議之間的轉換
- 同一序列化協議多版本之間的轉換
- 私有和公開通用的序列化協議之間的轉換
- 對單體時代或者微服務時代的業務進行改造升級
- 業務應用和 sidecar 同時升級帶來的額外運營維護
- 有狀態的 Sidecar 的開發測試與維護
- 應用和代理的優雅退出和平滑升級
- 不同技術體系之間的互通
- Mesh 模式和非 Mesh 模式之間的切換
面對這些難度層層遞進的工作,中小廠家很有可能就會退縮到微服務技術體系。其最根本的原因是:同等級別的業務形態下,技術復雜性守恒,總成本守恒。一如微服務技術至于單體技術:各個單一服務都被拆分的足夠簡單,但單體技術的復雜性轉換為了巨量服務之間的復雜性。
另一種 Mesh
以 Service Mesh 技術為代表的的云原生技術體系根植于以 K8s 為代表的的云原生基礎設施之上。
1. 協議標準化
云原生中間件 Proxy 的下一站除了被動地去兼容各種協議,更應該主動的去統一序列化協議,如自身直接支持 Protobuf v3 協議,業務也采用這種可保證向后兼容的協議即可。
除了被動地去兼容各種通信框架做互聯互通,可以更主動地向事實上的通信框架 gRPC 或者通信協議 HTTP 靠攏。gRPC 有各種語言的 SDK 庫。各種語言自身會主動提供 HTTP 通信協議庫,且 HTTP2.0 向后兼容 HTTP 1.1。例如微軟的 Dapr,就直接提供 gRPC 和 HTTP 兩種通信協議的 API,上層業務需要做的是選擇其中一種通信協議的 API 進行開發。
2. Service Proxy
一些的云原生時代的事實上的標準通信設施有:2008 年開源的 protobuf v2 和 2014 年開源的 protobuf v3 統一了序列化協議;2016 年 gRPC 發布 v1 之后逐漸成了跨語言首選的通信庫。
除了序列化協議和通信協議,微服務時代的中間件體系大概有如下技術棧:
- RPC,其代表是 Dubbo/Spring Cloud/gRPC 等。
- 限流熔斷等流控,如 hystrix/sentinel 等。
- Cache,其代表是 Redis。
- MQ,其代表有 kafka/rocketmq 等。
- 服務跟蹤,如兼容 Opentracing 標準的各種框架。
- 日志收集,如 Flume/Logtail 等。
- 指標收集,如 prometheus。
- 事務框架,如阿里的 seata。
- 配置下發,如 apollo/nacos。
- 服務注冊,如 zookeeper/etcd 等。
- 流量控制,如 hystrix/sentinel 等。
- 搜索,如 ElasticSearch。
- 流式計算,如 spark/flink。
把各種技術棧統一到一種事實上的技術標準,才能反推定義出不可變的中間件設施的終態。把上面這些事實上的中間件梳理一番后,整體工作即是:
- 統一定義各服務的標準模型
- 定義這些標準模型的可適配多種語言的 API
- 一個具備通信和中間件標準模型 API 的 Proxy
- 適配這些 API 的業務
上圖定義一種不同于 istio + Envoy 的另一種可能的 Proxy Service Mesh 進化路徑。該 Service Mesh 模型下的 sidecar 不僅僅是一個 Local Proxy,更應該是一個提供各個中間件技術棧標準能力的 Service Proxy。
Service Proxy 可能是一個集狀態管理、event 傳遞、消息收發、分布式追蹤、搜索、配置管理、緩存數據、旁路日志傳輸等諸多功能于一體的 Proxy, 也可能是分別提供部分服務的多個 Proxy 的集合,但對上提供的各個服務的 API 是不變的。
3. Application Mesh
或者更進一步,可以把 Service Proxy 拆分為兩個 Proxy:
- 仍然以現有的以劫持網絡流量的 sidecar 形式存在的 Local Proxy。
- 另一個專門提供各個 Service API 的 Application Proxy。
Application Proxy 可以是一個獨立存在的進程或者容器,也可以是一個可被應用調用嵌入式的 SDK 庫。無論是 Proxy 形式還是 Proxyless 形式,這都是一種新形態的 Service Mesh,可被稱之為 Application Mesh。
Application Proxy 可以依賴于 Local Proxy,亦可不依賴。如人們常說的三級緩存其實也是一種 Application Mesh 形態,從進程內的 local cache 到本機(容器、虛擬機 or 物理機)cache proxy 一直回溯到 cache cluster, 應用只需要從 local cache 處獲取數據即可。
當然,Application Mesh 亦可不依賴于特定的基礎設施平臺,包括 k8s,本文就不展開討論了。
除了 Service Mesh 技術帶來的收益,Application Mesh 具有如下更多的收益:
- 更好的擴展性與向后兼容性
基于標準的 API,其服務的不變性得到極大改善,不變性可以確保中間件的向后兼容與更好的擴展能力?;跇藴?API,第三方服務商可以在云廠商提供的基礎設施之上擴展出更多形態的中間件設施。
- 與語言無關
統一序列化協議和通信協議后,無特定語言依賴是很自然的事情。主流語言都會支持 HTTP 協議,gRPC 庫自身能夠提供主流語言的支持。無特定語言綁定帶來的另一個間接好處是更好的可移植性。
- 與云平臺無關
通過標準的服務讓應用做到無云平臺依賴,統一了中間件技術棧的平臺提供的技術能力相同的,云平臺使用者沒有被云服務提供商綁架的危險。
- 應用與中間件更徹底地解耦
通過標準協議和標準 API 讓應用與中間件徹底解耦,讓開發者在開發階段對新類型 Proxy 的有感,做到業務上線后業務對 Proxy 及其底層系統的升級過程無感知,即更好地平滑升級。
- 應用開發更簡單
基于標準 API,應用開發者甚至可以用單體時代的服務框架開發分布式應用,提升應用版本迭代速度。
- 更快的啟動速度
狀態從應用轉移到代理后,可以通過提前預熱代理,讓應用瞬時批量啟動。
未來的收益
任何技術都不是沒有代價的。誠如微服務技術帶來了服務數量的劇增,Service Mesh 技術帶來了吞吐的降低和延時的增加,但下一站的云原生中間件形態會帶來的是另一種新的價值形態,相比而言這個代價是可以接受的。
1. 業務價值
就其淺顯的技術價值而言,做到基礎中間件技術的統一后,即可做到無關語言,無關各個具體的中間件實體。減輕業務開發人員負擔,使其專注于業務邏輯,做到真正的快速迭代與平滑升級,提升研發效率的同時降低各種成本。
2. 云平臺無關
新形態帶來的商業價值就是無云平臺依賴,各平臺間相互之間的競爭就不會停留在某種獨有的核心技術優勢上,而是在同一技術體系下不斷降低服務成本,提供更好的用戶體驗、更強的服務能力與更親民的價格。
能夠且愿意實現這種終態 proxy 的組織當然不是各中小型業務廠家,所以統一了這些標準服務 API 的 Proxy 之下的應該是提供這些標準服務的各大云廠商。越早向統一服務模型靠攏的云廠商越快得利,越相信自己私有服務能力的云廠商越孤立。
3. 初創公司的機會
基于大廠提供的基礎設施,可以孕育出一個獨立的 service proxy 生態:一些第三方的初創廠家專職提供云原生中間件解決方案。
基于新形態的中間件方案,Low Code 或者 No Code 技術才能更好落地。單體時代的 IDE 才能更進一步 – 分布式時代的 IDE,基于各種形態中間件的標準 API 之對這些中間件的能力進行組合,以 WYSIWYG 方式開發出分布式應用。
4. 打破大廠內部藩籬
對一些大廠組織內部而言,可借助真正形態的 Service Mesh 技術??梢越y一大經濟實體內部技術棧,打破人為的各種異構隔離,提升研發運維效率和物理資源利用效率,降低整體人力與資源的交付運維成本。
5. 走向新時代
以統一技術形態的 Service Mesh 為基礎的云原生中間件技術體系真正發起起來,在其之上的 Serverless 才有更多的落地場景,廣大中小企業才能分享云原生時代的技術紅利,業務開發人員的編碼工作就會越來越少,編程技術也會越來越智能–從手工作坊走向大規模機器自動生產時代。
歡迎對 apache/dubbo-go 項目有興趣的同學歡迎釘釘搜索群號:31363295,加入交流群。
作者簡介
于雨(github @AlexStocks),dubbogo 社區負責人,一個有十多年服務端做著基礎架構和中間件研發一線工作經驗的程序員,陸續參與和改進過 Redis/Pika/Muduo/dubbo-go/Sentinel-go 等知名項目,目前在螞蟻金服可信原生部從事容器編排和 service mesh 工作。
推薦閱讀:《Dubbo 3.0 前瞻之對接 Kubernetes 原生服務》
總結
以上是生活随笔為你收集整理的无责任畅想:云原生中间件的下一站的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Serverless 场景下 Pod 创
- 下一篇: 在游戏运营行业,Serverless 如