天天看點

無責任暢想:雲原生中間件的下一站

簡介: 本文源自 2020 年 12 月 20 日作者在雲原生社群 meetup 第二期北京站演講 《Apache Dubbo-go 在雲原生時代的實踐與探索》的部分内容
無責任暢想:雲原生中間件的下一站

自從以 2013 年開源的 docker 為代表的的容器技術和以 2014 年開源的 K8s 為代表的容器編排技術登上舞台之後,相關技術從業人員從認知和體感上接受,雲原生時代真的到來了。

當然也有很多資深技術人員認為,雲原生時代要從 2010s 時以 OpenStack 為代表的虛機編排時代開始。當然,也有人說其實雲原生技術誕生很早,可以從巨型機時代在巨型機上虛拟出若幹小型機開始追溯。

在雲原生時代,不變鏡像作為核心技術的 docker 定義了不可變的單服務部署形态,統一了容器編排形态的 k8s 則定義了不變的 service 接口,二者結合定義了服務可依賴的不可變的基礎設施。有了這種完備的不變的基礎設定,就可以定義不可變的中間件新形态 -- 雲原生中間件。

雲原生時代的中間件,包含了不可變的緩存、通信、消息、事件(event) 等基礎通信設施,應用隻需通過本地代理即可調用所需的服務,無需關心服務能力來源。

微服務架構

從最早的單體應用時代到分布式技術時代,流行的是微服務技術。微服務時代各大公司都沉澱出了具有代表性的一些服務通信架構,如 Google 的 gRPC,阿裡的 Dubbo 和 HSF,百度的 bRPC 等等。多個服務通信架構之間的競争,基本上是在大公司之間進行角力。

站在使用者的角度,當然期待一個網絡架構在進化過程中能夠保持向前相容性,多個架構之間保持互通性。

服務架構的向後相容性

==============

通信架構的基礎是通信協定和序列化協定,其中很重要的問題就是新版本協定對舊版本的向後相容性。在一個組織中一般都使用統一的通信架構,但現實中可能因為各種原因,同一個架構的序列化協定或者通信協定的向後相容能力差,會導緻使用不同版本通信架構的各個服務之間的異構化。如采用了 pb v2 和 pb v3 的通信架構不相容,不遑多讓的 Thrift 0.8.x 與 Thrift 0.9.x 之間也不相容。

不過 Protobuf v3 或者 Protobuf v2 的各個子版本之間的向前和先後相容性還是不錯的,但還是有一些弱雞公司的内部序列化協定無論是否采用 TLV 形式,其協定各個版本的之間還是無法相容,進而導緻各個子版本的服務架構互相異構,最終導緻使用了不同版本的服務架構的業務背上大量包袱無法快速演進,有些新版本的業務中存在各種神邏輯可能不是為了相容舊版本的業務邏輯,而是為了相容舊版本架構的通信協定。

多架構之間的互通性

=============

一個常識是,組織規模膨脹到足夠大的程度後,不可能有一個通用的架構适用于所有的場景,一些大經濟實體随着業務體量變大,業務類型變得龐雜,不可避免地存在一些重複的輪子,這些龐大規模的組織因為其規模效應,任何一個适用于特定場景的架構隻要能在内部找到若幹落地應用場景就足以讓其開發維護成本變得可負擔且收益甚大。

公司内部各個分公司之間可能存在不同服務架構導緻各個服務之間通信異構化越來越嚴重,如阿裡内部早前存在異構的 Dubbo 和 HSF(目前阿裡内部 HSF 和 Dubbo 已經開始融合, HSF 已經采用 Dubbo 作為核心以 Dubbo 插件的形式存在),如當下的阿裡的 HSF 和各個收來的新公司之間的網絡通信,其間通信可能不得不借助于 Proxy 形式的通信網關。

每個服務架構各個子版本之間需要保持向後相容,各個服務架構之間的相容可能需要網關代理。

多語言架構之間的互聯

除了序列化協定、通信架構的異構外,還普遍存在着因為各個不同語言技術棧之間差異導緻的異構:每種語言都有個各自的序列化協定和通信架構。如 Java 世界就存在着 Spring Cloud 和 Dubbo 兩大服務治理架構,Spring Cloud 尚無多語言版本實作,相比之下 Dubbo 的多語言工作稍好一些。

打通打平不同的技術體系

===============

同一實體内部不同公司之間有兩三個不同服務架構的情況已經算是很好了,大公司組織内部可以容忍适量的重複造輪子,但大量的重複造輪子就過猶不及了。據說有巨頭内部不同部門之間存在各自的 RPC 服務架構 ,其總體服務架構超 100+!

随着國内網際網路行業發展由于頭部效應趨向性明顯,在大魚吃小魚的時代背景下,大公司與收購來的公司之間的技術體系異構也是雲原生時代中間件面臨的一個問題,二者之間因為業務規模不同帶來的服務注冊中心、配置中心、語言技術棧、服務鑒權、緩存和存儲等諸多技術不統一。有的剛收來的公司甚至使用了大公司的競争對手的雲平台,這就又帶來了平台級的差異,諸如此類的異構問題不一而足。

借助網絡代理技術,可以初步快速打通不同技術體系之間的異構差異。

通信代理的必要性

============

除了南北向通信的網絡接入層代理外,微服務時代使用同一通信架構的各個服務實體之間直接進行通信,很少聽說各個服務實體之間通過代理 Proxy 進行通信,其根由是各個通信實體之間通信架構同構。

或者說,網絡通信代理被各個強悍的通信架構給消化掉,以 Proxyless SDK 的形式存在,如服務發現、服務路由、容災限流、負載均衡等功能都存在于各個服務架構的 SDK 中。

但随着多協定多語言等各種因素導緻的各個架構之間的各種異化,大家普遍相信:沒有什麼差異不是一層 Proxy 解決不了的。

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 中。

Sidecar 的能力

Proxy Service Mesh 中 sidecar 的一個典型代表是 envoy,其本質是一個具備通信能力的 local proxy,具備如下資料面能力:

流量控制

序列化協定轉換

通信協定轉換

資料路由控制

實際上, envoy 僅僅是提供了這些能力的接口,至于具體的序列化協定轉換、通信協定轉換插件等工作還是需要相關的基礎設施開發人員去做的。

除了序列化協定和通信協定轉換,中間件的其他能力向 Proxy 下沉的過程中,都需要做大量的 envoy filter 層面的工作。相對于 Proxyless 形式的 Service Mesh,Proxy Service Mesh 成本沒有任何變化,其對業務的侵入性也沒有減輕更多。

協定下沉

========

如果說 Proxyless Service Mesh 形态下的 SDK 更新需要業務層面做很多改造,Proxy Service Mesh 形态下的業務從 Proxyless 向 Proxy 形态更新過程中改造成本也不可謂不小。如果通信協定采用了 Protobuf V3,Proxy Serivce Mesh 形态下的業務更新協定時可能做到平滑更新:隻更新 Proxy 不用更新業務服務實體。但現實是一些公司内部的私有協定根本做不到向後相容,其成本就是更新協定時服務網格的 Proxy 和業務實體一起更新,至于期望的平滑更新就很難做到了。

諸般問題的核心是 Local Proxy 沒有統一通信協定和序列化協定,僅僅注重于流量劫持。

有狀态的應用

==========

Service Mesh 技術的一些愛好者假設服務實體是一個無狀态的服務,其代理也當然是一個無狀态的 sidecar,然後宣傳 Service Mesh 時代的各種紅利。

至于那些有狀态的應用,大公司有人有錢耗費巨量人日成本後,把狀态轉移到 Proxy 中去,讓應用無狀态,但業務無感覺的平滑更新是就難做到了。這個成本對大經濟實體來說當然是可負擔且收益甚大的,但不是一些中小廠家所能承受的,他們在踩完各種坑後,可能神奇的發現他們根本沒有實力實作有狀态的 sidecar。

複雜性守恒

=========

總結一番,基于 sidecar 搭建一個 Proxy Service Mesh 可能存在如下工作:

不同序列化協定轉換

不同通信協定之間的轉換

同一序列化協定多版本之間的轉換

私有和公開通用的序列化協定之間的轉換

對單體時代或者微服務時代的業務進行改造更新

業務應用和 sidecar 同時更新帶來的額外營運維護

有狀态的 Sidecar 的開發測試與維護

應用和代理的優雅退出和平滑更新

不同技術體系之間的互通

Mesh 模式和非 Mesh 模式之間的切換

面對這些難度層層遞進的工作,中小廠家很有可能就會退縮到微服務技術體系。其最根本的原因是:同等級别的業務形态下,技術複雜性守恒,總成本守恒。一如微服務技術至于單體技術:各個單一服務都被拆分的足夠簡單,但單體技術的複雜性轉換為了巨量服務之間的複雜性。

另一種 Mesh

以 Service Mesh 技術為代表的的雲原生技術體系根植于以 K8s 為代表的的雲原生基礎設施之上。

協定标準化

雲原生中間件 Proxy 的下一站除了被動地去相容各種協定,更應該主動的去統一序列化協定,如自身直接支援 Protobuf v3 協定,業務也采用這種可保證向後相容的協定即可。

除了被動地去相容各種通信架構做互聯互通,可以更主動地向事實上的通信架構 gRPC 或者通信協定 HTTP 靠攏。gRPC 有各種語言的 SDK 庫。各種語言自身會主動提供 HTTP 通信協定庫,且 HTTP2.0 向後相容 HTTP 1.1。例如微軟的 Dapr,就直接提供 gRPC 和 HTTP 兩種通信協定的 API,上層業務需要做的是選擇其中一種通信協定的 API 進行開發。

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 是不變的。

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 技術帶來了吞吐的降低和延時的增加,但下一站的雲原生中間件形态會帶來的是另一種新的價值形态,相比而言這個代價是可以接受的。

業務價值

就其淺顯的技術價值而言,做到基礎中間件技術的統一後,即可做到無關語言,無關各個具體的中間件實體。減輕業務開發人員負擔,使其專注于業務邏輯,做到真正的快速疊代與平滑更新,提升研發效率的同時降低各種成本。

雲平台無關

新形态帶來的商業價值就是無雲平台依賴,各平台間互相之間的競争就不會停留在某種獨有的核心技術優勢上,而是在同一技術體系下不斷降低服務成本,提供更好的使用者體驗、更強的服務能力與更親民的價格。

能夠且願意實作這種終态 proxy 的組織當然不是各中小型業務廠家,是以統一了這些标準服務 API 的 Proxy 之下的應該是提供這些标準服務的各大雲廠商。越早向統一服務模型靠攏的雲廠商越快得利,越相信自己私有服務能力的雲廠商越孤立。

初創公司的機會

===========

基于大廠提供的基礎設施,可以孕育出一個獨立的 service proxy 生态:一些第三方的初創廠家專職提供雲原生中間件解決方案。

基于新形态的中間件方案,Low Code 或者 No Code 技術才能更好落地。單體時代的 IDE 才能更進一步 -- 分布式時代的 IDE,基于各種形态中間件的标準 API 之對這些中間件的能力進行組合,以 WYSIWYG 方式開發出分布式應用。

打破大廠内部藩籬

對一些大廠組織内部而言,可借助真正形态的 Service Mesh 技術棧可以統一大經濟實體内部技術棧,打破人為的各種異構隔離,提升研發運維效率和實體資源利用效率,降低整體人力與資源的傳遞運維成本。

走向新時代

以統一技術形态的 Service Mesh 為基礎的雲原生中間件技術體系真正發起起來,在其之上的 Serverless 才有更多的落地場景,廣大中小企業才能分享雲原生時代的技術紅利,業務開發人員的編碼工作就會越來越少,程式設計技術也會越來越智能--從手工作坊走向大規模機器自動生産時代。

繼續閱讀