组合式应用新利器?SaaS新时代事件网格如何解决集成标准化问题
阅读原文时间:2022年04月19日阅读:1

摘要:组合式应用需要面临的一个难题是如何解决各个应用之间的集成标准问题,比如应用可能仅支持HTTP、TCP等协议中的一种,而缺乏统一的通讯标准就给业务落地该架构带来了困难。下面介绍事件网格(EventGrid)是如何解决这一问题。

在SaaS新时代下,业务适应性需求引导企业转向支持快速、安全和高效应用变化的技术架构。组合式应用作为加速数字化的关键技术,是Gartner提出的在2022年重要战略技术之一,它由以业务为中心的模块化组件构建而成,使技术和业务团队可以更敏捷、更有效地重用代码。组合式应用需要面临的一个难题是如何解决各个应用之间的集成标准问题,比如应用可能仅支持HTTP、TCP等协议中的一种,而缺乏统一的通讯标准就给业务落地该架构带来了困难。下面介绍事件网格(EventGrid)是如何解决这一问题。

事件网格是华为云中间件在云原生时代推出的新一代无服务器事件总线,承载和管理来自传统应用、云服务应用和SaaS合作伙伴应用的各类事件,帮助应用开发者轻松搭建高可用、松耦合、分布式的事件驱动架构。作为Serverless 架构下事件驱动架构的关键一环,它提供弹性、异步、去中心化的事件治理服务,对事件提供汇聚、模型校验、过滤、路由、转换和推送等核心功能,还包括容错重试、死信储存、事件查询跟踪、事件工作流等增强特性。

从以上EventGrid总体架构图可以看出,EventGrid 对接了一系列云服务作为事件源。这些云服务包括分布式消息服务(如RocketMQ、Kafka和 Pulsar)、对象存储服务 (OBS) 和分布式缓存服务(Redis) 。事件源会产生管理类、数据类和自定义事件,然后通过EventGrid SDK推送到EventGrid的事件总线 (Bus Runtime) 的 事件通道中。事件总线为EventGrid用户以租户为单位配置事件通道,一个租户下允许有多个事件通道,承载来自不同事件源的事件。比如默认事件通道存储华为云产生的事件,而自定义事件通道存储应用和微服务的事件。EventGrid用户通过订阅的方式消费事件,通过在订阅的配置项里定义事件源、事件目标、事件过滤和转换规则,EventGrid就能从事件总线里提取相关事件,然后实时推送到所定义的事件目标中。推送方式可以是同步和异步:同步推送一般是以HTTP协议,适合应用和微服务;异步推送一般是推动到SaaS伙伴应用的消息队列中。

所以,华为云EventGrid通过事件驱动的方式联动周边的云服务、云原生应用和SaaS伙伴应用,实现服务和应用之间解耦,专注发挥自己服务的优势,通过各种事件模型连接,为华为云创造更多的应用场景,丰富华为云的开发者生态。

华为云EventGrid引入了开源明星项目Apache EventMesh,作为其运行时引擎。Apache EventMesh 作为云原生的事件驱动架构中间件,用于分离应用程序和后端事件存储(Event Store),支持广泛的应用场景,包括混合云和传统数据中心,以及不同技术栈的分布式架构。

Apache EventMesh的理念和EventGrid很类似。它也是连接事件源,聚集事件,然后把事件推送到客户端。它的亮点是其内核可以支持插件化。根据不同的事件应用场景,可以接入不同的插件来匹配。比如在事件链接器 (Event Connector)方面, 可以对接RocketMQ Connector或者 Kafka Connector。在HTTP授权(Http-Auth)方面, 可以引用BasicAuth或者TokenAuth。 这样灵活的架构有助于打造生态系统,对接不同的产品和服务。

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

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 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 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 Stub)。使用non-Blocking Stub客户端发送请求后不需要等待服务器回复,继续进行执行下一步操作。这很适合在大量事件生产的场景。但是在事件RequestReply场景下,客户端需要同步的等待事件成功推送到事件消费者,我们就需要gRPC的阻塞存根 (Blocking Stub)。通过给客户端提供的两种选择,可以更灵活的满足不同的事件生产和消费场景。目前EventMesh SDK 使用了Blocking Stub, 下一步是使用non-Bocking Stub 提高客户端高并发性能。

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模型定义,重新生成代码即可。迭代快速,维护简单。

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。

通过整合TCP和 HTTP协议,EventMesh Runtime和 SDK架构更加轻量化,减少了代码维护。同时用户使用SDK就不需要考虑使用场景要选哪一种协议。用户不需要学习和感知SDK层面的通讯协议,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。

2. 启动Event Publisher, 运行

Eventmesh-example/src/main/java/
org.apache.eventmesh.grpc.pub.eventmeshmessage.AsyncPublishInstance

3. 启动Event Subscriber, 运行

Eventmesh-example/src/main/java/
org.apache.eventmesh.grpc.sub.app.SpringBootDemoApplication

作为组合式应用新利器,gRPC的引入无疑是集成标准化的一大助力。当然,除了通讯标准外,还有schema、governance等集成标准需要统一,事件网格会在这些领域继续做出自己的探索。

点击关注,第一时间了解华为云新鲜技术~

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章