組合式應用新利器?SaaS新時代事件網格如何解決整合標準化問題

華為雲開發者社群發表於2022-04-18
摘要:組合式應用需要面臨的一個難題是如何解決各個應用之間的整合標準問題,比如應用可能僅支援HTTP、TCP等協議中的一種,而缺乏統一的通訊標準就給業務落地該架構帶來了困難。下面介紹事件網格(EventGrid)是如何解決這一問題。

在SaaS新時代下,業務適應性需求引導企業轉向支援快速、安全和高效應用變化的技術架構。組合式應用作為加速數字化的關鍵技術,是Gartner提出的在2022年重要戰略技術之一,它由以業務為中心的模組化元件構建而成,使技術和業務團隊可以更敏捷、更有效地重用程式碼。組合式應用需要面臨的一個難題是如何解決各個應用之間的整合標準問題,比如應用可能僅支援HTTP、TCP等協議中的一種,而缺乏統一的通訊標準就給業務落地該架構帶來了困難。下面介紹事件網格(EventGrid)是如何解決這一問題。

事件網格是華為雲中介軟體在雲原生時代推出的新一代無伺服器事件匯流排,承載和管理來自傳統應用、雲服務應用和SaaS合作伙伴應用的各類事件,幫助應用開發者輕鬆搭建高可用、鬆耦合、分散式的事件驅動架構。作為Serverless 架構下事件驅動架構的關鍵一環,它提供彈性、非同步、去中心化的事件治理服務,對事件提供匯聚、模型校驗、過濾、路由、轉換和推送等核心功能,還包括容錯重試、死信儲存、事件查詢跟蹤、事件工作流等增強特性。

組合式應用新利器?SaaS新時代事件網格如何解決整合標準化問題

從以上EventGrid總體架構圖可以看出,EventGrid 對接了一系列雲服務作為事件源。這些雲服務包括分散式訊息服務(如RocketMQ、Kafka和 Pulsar)、物件儲存服務 (OBS) 和分散式快取服務(Redis) 。事件源會產生管理類、資料類和自定義事件,然後通過EventGrid SDK推送到EventGrid的事件匯流排 (Bus Runtime) 的 事件通道中。事件匯流排為EventGrid使用者以租戶為單位配置事件通道,一個租戶下允許有多個事件通道,承載來自不同事件源的事件。比如預設事件通道儲存華為雲產生的事件,而自定義事件通道儲存應用和微服務的事件。EventGrid使用者通過訂閱的方式消費事件,通過在訂閱的配置項裡定義事件源、事件目標、事件過濾和轉換規則,EventGrid就能從事件匯流排裡提取相關事件,然後實時推送到所定義的事件目標中。推送方式可以是同步和非同步:同步推送一般是以HTTP協議,適合應用和微服務;非同步推送一般是推動到SaaS夥伴應用的訊息佇列中。

所以,華為雲EventGrid通過事件驅動的方式聯動周邊的雲服務、雲原生應用和SaaS夥伴應用,實現服務和應用之間解耦,專注發揮自己服務的優勢,通過各種事件模型連線,為華為雲創造更多的應用場景,豐富華為雲的開發者生態。

以EventMesh 為引擎

華為雲EventGrid引入了開源明星專案Apache EventMesh,作為其執行時引擎。Apache EventMesh 作為雲原生的事件驅動架構中介軟體,用於分離應用程式和後端事件儲存(Event Store),支援廣泛的應用場景,包括混合雲和傳統資料中心,以及不同技術棧的分散式架構。

Apache EventMesh的理念和EventGrid很類似。它也是連線事件源,聚集事件,然後把事件推送到客戶端。它的亮點是其核心可以支援外掛化。根據不同的事件應用場景,可以接入不同的外掛來匹配。比如在事件連結器 (Event Connector)方面, 可以對接RocketMQ Connector或者 Kafka Connector。在HTTP授權(Http-Auth)方面, 可以引用BasicAuth或者TokenAuth。 這樣靈活的架構有助於打造生態系統,對接不同的產品和服務。

EventMesh gRPC特性

Apache EventMesh 最新發布的v1.4.0版本相比之前的版本又增加了多個重要特性和架構優化。其中一個亮點是對於gRPC的支援。gRPC是基於HTTP/2的現代高效能RPC (Remote Procedure Call) 框架。相比HTTP 協議,gRPC支援Client 和 Server雙向非同步通訊,通過Protobuf 定義API介面資料模型,支援多語言SDK。 通過實現gRPC協議,Apache EventMesh 可以整合原有的TCP和HTTP協議,讓當前執行時輕量化。 同時其SDK可以擴充套件到多語言支援,比如Java、Go、JavaScript等等。

Protobuf 設計

EventMesh 引入gRPC首先從設計Protobuf定義(eventmesh-client.proto) 開始。我們在eventmesh-client.proto檔案裡定義EventMesh事件傳送和訂閱服務的方法和事件模型。由於篇幅原因,以下僅介紹定義的重點部分,完整的文件請見:

https://github.com/apache/incubator-eventmesh/blob/master/eventmesh-protocol-plugin/eventmesh-protocol-grpc/src/main/proto/eventmesh-client.proto

1、事件傳送服務提供以下介面。

service PublisherService {
 
   rpc publish(SimpleMessage) returns (Response);

   rpc requestReply(SimpleMessage) returns (SimpleMessage);

   rpc batchPublish(BatchMessage) returns (Response);
}

事件是以SimpleMessage的資料模型呈現。事件傳送支援同步傳送、非同步傳送和批量傳送三種模式。其中同步傳送是指事件生產者傳送事件到EventMesh,並等待事件成功推送到事件消費者,並收到事件消費者的返回,才算完成整個端到端的事件傳送過程;非同步傳送是指事件生產者傳送事件到EventMesh即可,無需等待事件被成功推送到事件消費者;批量傳送是指非同步傳送一批事件到EventMesh。

2、事件模型如下:

 message RequestHeader {
    string env = 1;
    string region = 2;
    string idc = 3;
    string ip = 4;
    string pid = 5;
    string sys = 6;
    string username = 7;
    string password = 8;
    string language = 9;
    string protocolType = 10;
    string protocolVersion = 11;
    string protocolDesc = 12;
}

message SimpleMessage {
   RequestHeader header = 1;
   string producerGroup = 2;
   string topic = 3;
   string content = 4;
   string ttl = 5;
   string uniqueId = 6;
   string seqNum = 7;
   string tag = 8;
   map<string, string> properties = 9;
}

事件模型可以支援多種協議,包括CNCF CloudEvents、OpenMessenging和EventMesh原生事件協議,這些協議都在SimpleMessage的protocol 相關欄位中體現。 另外模型中帶有 producerGroup和topic 用於事件的路由;ttl、uniqueId和seqNum則是用於事件的管理。請求頭裡帶有事件生產者的基本資訊: env、region、idc、ip和sys。

3、事件訂閱服務提供以下介面:

service ConsumerService {

   rpc subscribe(Subscription) returns (Response);

 
   rpc subscribeStream(stream Subscription) returns (stream SimpleMessage);

   rpc unsubscribe(Subscription) returns (Response);
}

事件訂閱支援兩種方式:叢集(cluster) 和廣播(broadcast) 。叢集模式中,事件消費者叢集裡只有一個例項能消費到事件;廣播模式讓叢集裡每一個例項都消費到事件。這些訂閱模式是在訂閱資料模型裡定義的。另外訂閱服務提供兩種訂閱介面:subscribe API和 subscribeStream API。Subscribe API 是通過url方式 推送事件到消費者,這裡url又叫 webhook。這種場景適合雲原生微服務和自定義應用及函式。subscribeStream API 是通過gRPC 雙向流(Bidirectional Streaming) 推送事件到消費者 ,同時可以讓事件消費者返回確認資訊 (Ack) 給事件生產者。這就滿足了生產者RequestReply同步事件傳送的需求。

服務端的多執行緒併發

為了提高事件生產和消費的效能,EventMesh 服務端 (EventMesh Runtime) 在 gRPC的服務裡定義了執行緒池 (ThreadPool),而且針對事件生產和消費的對效能要求的不同,配置獨立的引數。這些引數都可以在EventMesh配置檔案 (eventmesh.properties)裡找到。比如以下分別是事件生產,訂閱和推送的執行緒數。

eventMesh.server.sendmsg.threads.num=50
eventMesh.server.clientmanage.threads.num=30
eventMesh.server.pushmsg.threads.num=50

當gRPC服務啟動後,它會監聽客戶端的請求,一旦有新請求進來,它會分發到對應服務的執行緒池,然後讓對應的處理器 (Processor)處理,這樣就不會阻塞下一個請求的處理,從而提高了併發量。

public void publish(SimpleMessage request, StreamObserver<Response> responseObserver){
    cmdLogger.info("cmd={}|{}|client2eventMesh|from={}|to={}", "AsyncPublish",
        EventMeshConstants.PROTOCOL_GRPC, request.getHeader().getIp(),
        eventMeshGrpcServer.getEventMeshGrpcConfiguration().eventMeshIp);

    EventEmitter<Response> emitter = new EventEmitter<>(responseObserver);

    threadPoolExecutor.submit(() -> {
        SendAsyncMessageProcessor sendAsyncMessageProcessor = new SendAsyncMessageProcessor(eventMeshGrpcServer);
        try {
            sendAsyncMessageProcessor.process(request, emitter);
        } catch (Exception e) {
            logger.error("Error code {}, error message {}", StatusCode.EVENTMESH_SEND_ASYNC_MSG_ERR.getRetCode(),
                StatusCode.EVENTMESH_SEND_ASYNC_MSG_ERR.getErrMsg(), e);
            ServiceUtils.sendRespAndDone(StatusCode.EVENTMESH_SEND_ASYNC_MSG_ERR, e.getMessage(), emitter);
        }
    });
}

比如以上程式碼是事件傳送服務 (publish service) 的實現。它使用了 threadPoolExecutor把事件傳送到執行緒池讓下游SendAsyncMessageProcessor處理。

事件消費者的負載均衡和重試

在事件消費者方面,EventMesh 支援負載均衡。使用者可以在事件訂閱裡指定多個事件消費者來消費事件。每個消費者會是一個URL(Webhook) 或者 gRPC 客戶端 (stream),這些消費者可以是叢集或者是主備方式部署。那麼EventMesh會通過演算法計算選擇其中一個消費者去推送事件。如果當前消費者無法消費事件,那麼EventMesh會選下一個消費者。EventMesh預設以輪詢方式選擇消費者推送事件,來達到消費者的負載均衡。開發者可以通過外掛提供其他演算法來選擇消費者。

事件推送失敗,可能是網路原因,當前消費者繁忙或下線。EventMesh先嚐試重試,每次重試會間隔幾秒鐘,最多重試3次。如果3次重試失敗了,EventMesh才會選擇下一個消費者。重試間隔時間可以在配置檔案裡定義。

gRPC non-Blocking 和 Blocking Stub

為了提高客戶端效能,gRPC提供了非阻塞存根 (non-Blocking Stub)。使用non-Blocking Stub客戶端傳送請求後不需要等待伺服器回覆,繼續進行執行下一步操作。這很適合在大量事件生產的場景。但是在事件RequestReply場景下,客戶端需要同步的等待事件成功推送到事件消費者,我們就需要gRPC的阻塞存根 (Blocking Stub)。通過給客戶端提供的兩種選擇,可以更靈活的滿足不同的事件生產和消費場景。目前EventMesh SDK 使用了Blocking Stub, 下一步是使用non-Bocking Stub 提高客戶端高併發效能。

支援多語言SDK

Apache EventMesh v1.3.0之前只提供Java SDK。這對於接入其他雲原生的應用場景有侷限。因為很多雲服務都是用Go, Python和JavaScript (NodeJS 框架) 語言開發的 。一些雲原生的開源專案,比如KNative、Dapr也是用Go作為開發語言。所以EventMesh 對支援多語言SDK有迫切需求,以繼續豐富應用開發者的生態。

gRPC的開發工具帶有多語言程式碼生成工具,包括Java、Go、NodeJS、PHP、Python、C#和C++等。EventMesh實現gRPC協議後可以藉助該工具,快速提供多語言的SDK。後續對於通訊API的改動只需要同步修改Protobuf模型定義,重新生成程式碼即可。迭代快速,維護簡單。

整合TCP和HTTP 協議

gRPC 支援4種Client和Server通訊RPC機制:Unary RPC、Server Streaming RPC、Client Streaming RPC和 Bidirectional Streaming RPC. EventMesh v1.4.0版本整合了v1.3.0版本的TCP 和 HTTP 的 SDK API,利用Unary RPC和 Bidirectional Streaming RPC,提供了 Event Publish、Broadcast、Request-Reply、Webhook Subscription和 Event Stream Subscription五種SDK API。

組合式應用新利器?SaaS新時代事件網格如何解決整合標準化問題

通過整合TCP和 HTTP協議,EventMesh Runtime和 SDK架構更加輕量化,減少了程式碼維護。同時使用者使用SDK就不需要考慮使用場景要選哪一種協議。使用者不需要學習和感知SDK層面的通訊協議,gRPC就能滿足他們事件生產和消費的所有場景。

開箱即用的gRPC樣例

為了讓EventMesh開發者更好的體驗gRPC新特性,社群提供了完善的使用文件和多個Event Publisher, Event Subscriber程式碼樣例。以下是相關文件:

https://github.com/apache/incubator-eventmesh/blob/master/docs/en/instructions/eventmesh-runtime-quickstart.md

https://github.com/apache/incubator-eventmesh/blob/master/docs/en/instructions/eventmesh-sdk-java-quickstart.md

第一個文件介紹如何部署和啟動EventMesh 伺服器。文件裡第一部分介紹如何遠端部署EventMesh 在虛擬機器裡,適合測試和生產環境的部署;第二部分介紹如何在本地開發環境裡部署EventMesh,適合常用的本地開發和除錯場景。以下命令列是展示如何在Linux 環境裡部署和啟動EventMesh Runtime

> tar -zxvf Eventmesh_1.3.0-release.tar.gz
> cd bin
> sh start.sh
> tail -f ./logs/eventmesh.out

第二個文件介紹如何使用EventMesh SDK開發應用生產和消費事件,包含了TCP、HTTP和gRPC 三部分。EventMesh工程專案裡帶有客戶端的程式碼樣例 (eventmesh-example),包括了gRPC Event Publisher、Event Subscriber的程式碼。比如,我們可以把EventMesh工程專案匯入Java IDE 裡 (比如Intellij IDEA)。按照以下步驟啟動 gRPC Event Publisher and Subscriber。

1. 修改eventmesh-examples/src/main/resources/application.properties指向已經部署的EventMesh Runtime。

組合式應用新利器?SaaS新時代事件網格如何解決整合標準化問題

2. 啟動Event Publisher, 執行

Eventmesh-example/src/main/java/
org.apache.eventmesh.grpc.pub.eventmeshmessage.AsyncPublishInstance
組合式應用新利器?SaaS新時代事件網格如何解決整合標準化問題

3. 啟動Event Subscriber, 執行

Eventmesh-example/src/main/java/
org.apache.eventmesh.grpc.sub.app.SpringBootDemoApplication
組合式應用新利器?SaaS新時代事件網格如何解決整合標準化問題

作為組合式應用新利器,gRPC的引入無疑是整合標準化的一大助力。當然,除了通訊標準外,還有schema、governance等整合標準需要統一,事件網格會在這些領域繼續做出自己的探索。

 

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章