內容摘要:Service Mesh 落地實踐三年,效果一直並不理想,到了該反思的時候了。Mecha 做爲面向服務的分佈式能力抽象層,是 Service Mesh 模式的天然進化版本,預計也將是雲原生化和 Mesh 化的必然趨勢,讓咱們將 Mesh 進行到底。java
Mecha 一詞,相信愛好動漫的同窗應該都不陌生。是的,就是你們熟悉的那個 Mecha(機甲):git
Mecha 這個詞之因此出如今這裏,主要是由於 Bilgin Ibryam 的這個博客文章 「Multi-Runtime Microservices Architecture」,提出了微服務架構的一個新的設想:Multiple Runtime。github
備註:這篇博客文章強烈推薦閱讀,我甚至建議在閱讀本文以前先閱讀這篇文章,由於我今天的內容,能夠視爲對這個文章的深度解讀和思考。爲了方便,這裏提供一份中文翻譯版本 多運行時微服務架構。
在這篇博客中,Bilgin Ibryam 首先分析並總結了分佈式應用的四大需求:編程
因爲每種需求存在的問題和侷限性,致使傳統解決方案如企業服務總線(ESB)及其變體(例如面向消息的中間件,更輕量級的集成框架等)再也不適用。隨着微服務架構的發展,以及容器和 Kubernetes 的普及和普遍使用,雲原生思想開始影響這些需求的實現方式。將來的架構趨勢是經過將全部傳統的中間件功能移至其餘運行時來全面發展,最後的目標是在服務中只需編寫業務邏輯。json
備註:詳情請見原文,爲了節約篇幅,這裏只作簡單概述,不徹底引用原文內容。
下圖是傳統中間件平臺和雲原平生臺的對比,傳統中間件以各類SDK的方式提供能力,而云原平生臺則經過各類外圍Runtime(典型如你們熟悉的Servicemesh/Istio):緩存
所以做者引入了 Multiple Runtime 的概念:服務器
做者提出:極可能在未來,咱們最終將使用多個運行時來實現分佈式系統。多個運行時,不是由於有多個微服務,而是由於每一個微服務都將由多個運行時組成,最有多是兩個運行時-自定義業務邏輯運行時和分佈式原語運行時。網絡
對多運行時微服務架構和 Mecha 的說明:架構
您還記得電影《阿凡達》和科學家們製做的用於去野外探索潘多拉的 Amplified Mobility Platform (AMP)「機車服」嗎?這個多運行時架構相似於這些 Mecha-套裝,爲人形駕駛員賦予超能力。在電影中,您要穿上套裝才能得到力量並得到破壞性武器。在這個軟件架構中,您將擁有構成應用核心的業務邏輯(稱爲微邏輯/micrologic)和提供強大的開箱即用的分佈式原語的 Sidecar Mecha 組件。Micrologic 與 Mecha 功能相結合,造成多運行時微服務,該服務將進程外功能用於其分佈式系統需求。最棒的是,Avatar 2 即將面世,以幫助推廣這種架構。咱們最終能夠在全部軟件會議上用使人讚歎的機甲圖片代替老式的邊車摩托車;-)。接下來,讓咱們看看該軟件架構的詳細信息。
這是一個相似於客戶端-服務器體系結構的雙組件模型,其中每一個組件都是獨立的運行時。它與純客戶端-服務器架構的不一樣之處在於,這兩個組件都位於同一主機上,彼此之間有可靠的網絡鏈接。這兩個組件的重要性至關,它們能夠在任一方向上發起操做並充當客戶端或服務器。其中的一個組件稱爲 Micrologic,擁有很是少的業務邏輯,把幾乎全部分佈式系統問題都剝離出去了。另外一個伴隨的組件是 Mecha,提供了咱們在本文中一直討論的全部分佈式系統功能(生命週期除外,它是平臺功能)。
做者在這裏正式提出了 Mecha 的理念:app
思路大致是:Smart Runtime, Dumb Pipes。
我對 Mecha 的理解是:業務邏輯在編碼開始階段應該是「裸奔」的,專一於業務邏輯的實現,而儘可能不涉及到底層實現邏輯;而在運行時,則應該裝備「機甲」,全副武裝,大殺四方。熟悉的味道是吧?標準而地道的雲原生思想。
做者在原文中探討了 Mecha 運行時的特性:
下面是我對上述特性的我的理解:
若是用一句話來總結,那麼我認爲 Mecha 的本質應該是:
「面向應用的分佈式能力抽象層」
如 Service Mesh 的本質是服務間通信的抽象層同樣,Mecha 的本質是應用須要的各類分佈式能力和原語,包括但不限於服務間通信。
從這個角度上說,Mecha 覆蓋的範圍是 Service Mesh 的超集:畢竟 Service Mesh 只覆蓋到應用的部分需求(服務間通信,還只限於同步/一對一/request-response 模式),還有更多的分佈式能力和原語有待覆蓋。
換一句話說,Mecha 的目標應該是:「將 Mesh 進行到底!」
做者指出:Mecha 的好處是業務邏輯和愈來愈多的分佈式系統問題之間的鬆耦合。
下圖是業務邏輯和分佈式系統問題在不一樣架構中的耦合:
其實思路和 Service Mesh 是一脈相承的,只是覆蓋的分佈式能力更普遍一些。
有一個問題:Mecha 會不會成爲微服務架構的演進的下一個形態?我我的的答案:是,隨着雲原生的推動,分佈式能力(以傳統中間件爲典型表明)下沉是大勢所趨,Mesh 化的範圍必然會繼續擴大,也就離 Mecha 的形態愈來愈近了。這也就是本文標題的立意所在,Mecha 會是微服務乃至雲原生的下一站。
在介紹完 Mecha/Multiple Runtime 的理念以後,咱們來看看目前微軟新推出來的 Dapr 項目 —— 這應該是業界第一個 Multiple Runtime 的開源實踐項目。
項目地址:https://github.com/dapr/dapr。
Dapr 是 Distributed Application Runtime (分佈式應用運行時)的縮寫,官方介紹說 Dapr 是「一種可移植的,事件驅動的運行時,用於構建跨雲和邊緣的分佈式應用」。
Dapr 的詳細介紹是:
Dapr 是一種可移植的、Serverless 的、事件驅動的運行時,它使開發人員能夠輕鬆構建彈性,無狀態和有狀態微服務,這些服務運行在雲和邊緣上,幷包含多種語言和開發框架。
Dapr 整理了構建微服務應用爲開放,獨立的構建塊的最佳實踐,使您可以使用本身選擇的語言和框架來構建可移植的應用程序。 每一個構建塊都是獨立的,您能夠在應用中使用其中的一個或多個。
Dapr 的功能和定位,下面這一張圖就能夠歸納了:
Dapr 提供的具體分佈式能力(building block)以下圖所示:
每一個 building block 提供的具體能力請參加 Dapr 的官方文檔:
https://github.com/dapr/docs/tree/master/concepts
咱們來看一下應用調用 Darp API 的例子,體驗一下使用 Dapr 的方式。
以 Service Invocation / 服務調用爲例:
部署和調用方式與 Service Mesh/ Istio 極爲類似,可是,差異在於:Dapr 是以提供 API 的方式提供 API 背後的能力,而不是提供提供協議代理的方式。
上圖,1 是 ServiceA 發起請求來調用一個遠程服務。其 HTTP request 以下所示:
POST/GET/PUT/DELETE http://localhost:<daprPort>/v1.0/invoke/<appId>/method/<method-name>
其中:
負載能夠存放在 HTTP body 中隨請求發送,如 json。
注意,雖然都是提供相同的功能,這裏體現了 Dapr(或者說背後的 Mecha)和 Service Mesh 在方式上的差別:暴露 API 仍是代理通信協議。
咱們看一個更明顯的例子,Dapr 提供的 「publish/subscriptions」 能力,讓應用能夠方便的發佈消息,或者訂閱主題並接收消息。下圖是應用發佈消息,請求直接發給 Dapr 便可:
例子中,參數 topic 指定了消息要發往的主題(例子中是 deathStarStatus)。後續 Dapr 會完成將消息入 queue,而後推送到訂閱了該 topic 的應用。接收消息的方式也相似,不過此次是 Darp 主動發起:
注意在這個調用期間,不管是收發消息,應用徹底不用理會底層 pub/sub 的實現機制(好比是 Kafka,仍是RocketMQ,仍是其餘公有云提供的消息機制),也徹底不用引入該實現機制的客戶端 SDK,只是簡單的使用 Darp定義的 API 便可,從而實現了和底層的解耦,以及「廠商不綁定」。
爲了進一步簡化調用的過程(畢竟發一個最簡單的 HTTP GET 請求也要應用實現 HTTP 協議的調用/鏈接池管理等),Dapr 提供了各個語言的 SDK,如 Java / Go / Python / dotNET / JavaScript / cpp / Rust 。另外同時提供 HTTP 客戶端和 gRPC 客戶端。
咱們以 Java 爲例,Java 的 client API 接口定義以下:
public interface DaprClient { Mono<Void> publishEvent(String topic, Object event); Mono<Void> invokeService(Verb verb, String appId, String method, Object request); ...... }
具體可見:
https://github.com/dapr/java-sdk/blob/master/sdk/src/main/java/io/dapr/client/DaprClient.java
前面介紹了Multiple Runtime / Mecha 的架構思想,以及參考實現之一的微軟 Dapr 項目。
因爲 Multiple Runtime / Mecha 這個思想很是的新,剛剛提出不久,而微軟 Dapr 項目也是一個新出來的項目,無論是理論思想仍是實踐都處於很是早期的狀態,也尚未造成完善的方法論。
特別申明:如下內容更可能是我我的當下的理解和感悟,僅表明我的意見,確定有不少不成熟甚至謬誤的地方,歡迎指正和探討。
隨着雲原生的深刻,應用須要的分佈式能力應該全面下沉,而不只僅侷限於Servicemesh提供的服務間通信能力;應用形態會朝純業務邏輯這個目標更進一步,應用更加的雲原生化。
這是大勢所趨,也是Mecha架構出現和發展的原動力。
Mecha 的使用方式和 Service Mesh 有很是大的差別:Mecha 強調的是提供分佈式能力給應用使用,這些能力最終以封裝完善的 API 的方式呈現。API 體現的是應用對能力的「需求」和「意願」,不涉及到如何實現,實現是 Mecha 的職責,採用什麼樣的實現也是由 Mecha 來控制。
在Service Mesh 下,不存在這個需求:Service Mesh 提供的是服務間通信能力,這個能力是由 Sidecar 來提供,沒有其餘更底層的實現,不存在隔離和替換的可能。受服務通信協議和報文 schema 的限制,Service Mesh 只能作請求的「轉發」,能力聚焦在「如何轉發」上,沒有其餘須要隔離和替代的能力。
當 Mecha 把能力擴展到 Servic Mesh 以外時,不少能力是由外部系統提供:好比 pub-sub 能力能夠由不一樣的 Message Queue 實現;狀態管理能力能夠鏈接不一樣的 Key-Value 實現。此時能力的隔離性和可替代性就成爲關鍵需求:解耦應用和能力實現,允許 Mecha 替換底層實現(進而實現供應商不鎖定等)。
在 Service Mesh 中,「零侵入」是一個很是強調的特性,爲此不惜引入 iptables 等流量劫持方案。「零侵入」在某些特殊場景下會發揮巨大的優點,如舊有應用不作改造的前提下接入 Service Mesh。好處天然不言而喻,但零侵入也有自身的限制:客戶端必須能發出符合服務器端要求的網絡通信請求,這個過程外部沒法插手。
對於服務間通信,這個不是大問題。可是對於其餘能力,因爲有和實現解耦的需求,再經過客戶端自行發起原生協議的請求就不合適了。所以,Mecha 中更傾向於採用低侵入的輕量級 SDK 方案,一樣也能夠實現跨語言和跨平臺,只是須要付出實現各類語言 SDK 的代價。因爲這個 SDK 足夠輕量,所以代價還不算很高。
而這些少許的工做量、少許的侵入,能夠換取輕量級 SDK 能提供的各類便利和配合(簡單理解:開後門),能夠實現能力的抽象和 API 的封裝。權衡利弊,Mecha 下更傾向於輕量級 SDK 方案。
Sidecar 部署模式,存在資源佔用、維護成本增長等缺點,在某些狀況下可能並不合適:
Mecha 下,部署模式不限定於 Sidecar ,在合適時允許選擇 Node 模式,甚至 Node 模式和 Sidecar 模式混合使用。
API 是分佈式能力的抽象,須要要對(開發上層業務應用的)客戶友好,簡單好用,穩定不變。這些 API 也須要標準化,被社區普遍接受和採納,才能實現廠商不鎖定和自由遷移,提高客戶價值。
另外,API 還須要配合配置使用,在把能力抽象爲 API 時,是不提供能力的細節控制的。這些控制將在運行時由 Mecha 根據配置實現,能夠理解爲:「API + 配置 = 完整的能力」。
API 和配置的制訂以及標準化,預計將會是 Mecha 成敗的關鍵。
Program to an interface, not an implementation.
Design Patterns: Elements of Reusable Object-Oriented Software (GOF, 1994)
Mecha 的精髓,要從上面這句名言開始:
我的理解,Mecha 的精髓就在於這幾個關鍵點:隔離/抽象/解耦/可替換。以下圖所示:
在 Mecha 的實現上,我理解的原則是這樣:
具體的職責劃分:
在 Mecha 架構中,Runtime 天然是整個架構的核心,扮演相似 Service Mesh 中數據平面的角色:
備註:Mecha 有很是多的能力,實現上也有很是多的細節,這裏先作一個 High Level 的概述。細節後面會有一系列文章一一覆蓋,歡迎多交流討論。
大概是在3月初,當時我第一次閱讀 「Multi-Runtime Microservices Architecture」 這篇文章,有一種豁然開朗的感受,尤爲是有不少以前在反覆考慮和權衡可是下不告終論的問題,在這個文章中獲得了清晰的解答。可謂受益不淺。
在 Service Mesh 探索和實踐的這三年中,遇到不少問題,有不少以前沒有想到過的問題浮現。好比,之前一直以爲 Service Mesh 中引入 Sidecar 帶來的最大麻煩會是性能,但實際上,從目前的實踐看,Sidecar 引入後帶來的維護代價纔是更使人頭疼的事情,相比之下 Sidecar 引入帶來的性能損失顯得無傷大雅。
總結一下我我的對 Mecha 架構的核心理解,主要是兩點:
正如曾有說法,說「微服務是 SOA 實踐中正確的部分(the Good Part)」,我但願在 Mecha 的探索和實踐中,可以從 Service Mesh 的實踐中吸收成功的經驗和失敗的教訓,但願 Mecha 也能成爲 Service Mesh 的 Good Part。但願在雲原生的演進路線中,Mecha 能夠繼微服務和 Service Mesh以後,成爲雲原生落地實踐的下一站。
回到現實,目前 Mecha 和 Multi-Runtime 仍是一個很是新的想法,Dapr 項目也纔剛剛起步,Mecha 要探索的道路還很漫長,一切都還須要摸索着前進。
在文章的最後,特別鳴謝 「Multi-Runtime Microservices Architecture」一文的做者 「Bilgin Ibryam」,我很是承認這篇文章中的思想和理念,分析概括的很是到位,提煉和昇華的能力使人佩服。
做者介紹:
Red Hat 的首席架構師,Apache Software Foundation 的 committer 和成員。開源的佈道師,博客做者,偶爾演講,著有書籍 Kubernetes Patterns 和 Camel Design Patterns 。
本文參考了 Bilgin Ibryam 出品的以下內容: