带有消息代理(例如 Kafka)的事件驱动微服务与反应式编程(RxJava、Project Reactor)以及改进的协议(RSocket)

Posted

技术标签:

【中文标题】带有消息代理(例如 Kafka)的事件驱动微服务与反应式编程(RxJava、Project Reactor)以及改进的协议(RSocket)【英文标题】:Event driven microservices with message brokers (e.g. Kafka) vs reactive programming (RxJava, Project Reactor) plus improved protocols (RSocket) 【发布时间】:2020-04-08 11:12:03 【问题描述】:

我们都同意,通过 HTTP 调用通信微服务的通常请求-响应方式会导致它们之间的耦合。这使我们采用了事件驱动的方法,在这种方法中,服务发布一些其他服务将响应的事件。为此,我们可以使用一些中间件,可以是 AMQ、RabbitMQ、Kafka 等。

不过,反应式编程社区也确实创建了一些优秀的项目,例如 Project Reactor 或 RxJava,它们将 HTTP 通信转变为伪消息驱动的解决方案。此外,随着RSocket等协议的到来,这种模式也延伸到了TCP/IP应用层。

RSocket/Reactive 微服务真的可以被认为是事件驱动的解决方案吗?它们不只是提高传统请求-响应系统性能的一种方式吗?

换一种说法:那些 Rsocket+Reactor 微服务不仍然像以前基于 HTTP 的微服务那样耦合吗?

在哪些场景下更值得推荐?

【问题讨论】:

【参考方案1】:

这里有一个 很多 需要解压,很抱歉篇幅太长。

您的问题标题正在描绘错误的二分法。这两者并不是相互竞争的想法,实际上恰恰相反,以至于reactive Kafka 是一个东西。

不过,反应式编程社区也确实创建了一些出色的项目,例如 Project Reactor 或 RxJava,它们将 HTTP 通信转变为伪消息驱动的解决方案。

Java 中的反应式库当然非常适合消息驱动的解决方案,但它们几乎可以用于任何事情(并且可以说经常用于它们并不总是最适合的情况!)

RSocket/Reactive 微服务真的可以被认为是事件驱动的解决方案吗?

Rsocket 和响应式微服务是两个不同的东西;虽然它们一起玩得很好并且经常一起使用,但它们并不是一回事。 RSocket 对于初学者来说要新得多,所以大多数反应式微服务可能已经没有使用它了。

响应式微服务,或以响应式方式编写的微服务,主要与它们的内部编写方式有关。作为反应式,后端是非阻塞的,因此可以说它们更有效——尤其是在需要通过长期连接发送数据流的情况下。非反应式服务必须在整个时间内保持一个单独的线程打开以管理该连接,而反应式服务可以简单地处于空闲状态,除非正在主动发送消息。

反应式微服务在内部肯定是事件驱动的。但是,这并没有说明反应式微服务可以用来进行通信的方式。它可以使用 RSocket、纯 HTTP、MQTT——你不能仅仅基于这个协议就不能保证它正在使用什么。

然而,

RSocket 是一个协议,它被设计为与响应式服务特别配合,在多种传输上工作,并且(作为二进制协议)更有效。这就引出了你的下一点:

它们不只是提高传统请求-响应系统性能的一种方式吗?

RSocket当然可以可以。您可以将它用作传统的请求/响应系统并获得改进的性能,而其他一切都保持“经典”。但是,它还支持数据流(单向和双向)以及协议级别的即发即弃语义和可恢复流,因此具有功能优势和性能优势。

这可能是一些混乱的根源,因为(没有 RSocket)人们可能会选择使用中间件纯粹是因为它更容易管理这些流(而不是专门解耦任何东西。)在这种情况下,是的,不需要中间件。

在传输层之上工作,RSocket 也不关心它在哪里使用,或者通过它发送什么 - 因此它在通过 TCP 的服务器到服务器环境中运行就像在双向服务器到客户端中一样快乐websocket上的环境。

那些 Rsocket+Reactor 微服务不是仍然像以前那样耦合基于 HTTP 的吗?

是的,它们仍然是耦合的——这不是 Rsocket 试图解决的问题。这是一个协议,它不是中间件。例如,Kafka 可以稍后原生支持 Rsocket。 (目前我看不出有迹象表明它会这样做,但从技术上讲,没有什么可以阻止它。)

在哪些场景下更值得推荐?

如果您使用中间件的唯一原因是轻松生成和管理数据流(而不是受请求/响应的约束),那么 Rsocket 与反应式库相结合现在可以说在协议层满足这些标准。

但是,如果您将中间件用于解耦目的,那么您几乎肯定会继续使用它。但是,继续使用上述中间件当然不会妨碍您在实现中使用响应式库和/或 Rsocket。

【讨论】:

嗨,Michael,首先感谢您抽出宝贵时间写出如此详细的答案。我完全同意你所说的一切。我的疑虑更多地与适当的反应式框架(Spring Webflux + Project Reactor)用于解耦微服务而不是使用像Kafka这样的东西有关。当前有一种“所有事件”趋势,我们希望通过消息传递来隔离有界上下文。正如您所说,在这种情况下,反应式应用程序不适合。 @codependent 反应式应用程序可能非常适合这种情况 - 但它们不是使用 RabbitMQ 等中间件的良好替代 /卡夫卡/别的什么,恕我直言。我怀疑随着时间的推移我们会看到更多响应式应用程序,但我非常怀疑这些应用程序会取代中间件,更有可能补充它们。【参考方案2】:

RSocket 的目的是提供一个应用程序到应用程序的通信协议,该协议更可能作为对等方相互交谈。 HTTP是为人机(客户端-服务器)通信而设计的。即使是 HTTP2 或传入的 3 也不会改变这种观点。两种协议之间的主要区别之一是双向流。所以不,RSocket 不只是试图提高请求-响应性能。

Kafka 和响应式流之间的一个关键区别是基础架构成本的观点。 Kafka 将缓冲所有数据,而响应式流将使用背压来协调发送方和接收方。 RSocket 只是将反应流扩展到网络协议级别。基本上就是第6层端到端的TCP滑动窗口。

【讨论】:

以上是关于带有消息代理(例如 Kafka)的事件驱动微服务与反应式编程(RxJava、Project Reactor)以及改进的协议(RSocket)的主要内容,如果未能解决你的问题,请参考以下文章

Redis、Kafka或RabbitMQ:哪个作为微服务消息代理最合适?

如何使用 Spring Cloud Stream Kafka 和每个服务的数据库实现微服务事件驱动架构

Kafka 和 REST 用于微服务之间的通信?

微服务、REST、事件溯源和数据一致性

Apache Kafka:重播主题中的消息

Spring Cloud入门 - 微服务与消息驱动