Kafka 消息 VS REST 调用

Posted

技术标签:

【中文标题】Kafka 消息 VS REST 调用【英文标题】:Kafka Msg VS REST Calls 【发布时间】:2020-01-11 03:25:22 【问题描述】:

如今,在微服务世界中,我在工作场所看到很多使用 kafka 消息传递的设计,而您可以使用微服务之间的 rest api 调用来实现类似的结果。从技术上讲,您可以完全停止使用 rest api 调用,而是使用 kafka 消息传递。我真的很想知道最佳实践,优缺点,何时在微服务之间使用 api 调用,何时使用 kafka 消息传递。

让我们举一个现实生活中的例子:

我有库存服务和供应商服务。日常供应商服务调用供应商 API 来获取新项目,这些需要移动到库存服务中。项目的数量最多可以是 10,000 个对象。

对于这个用例,是不是更好:

    从供应商 API 获取新数据后,调用库存服务的 REST API 来存储新项目。

    从供应商 API 获取新数据后,将它们作为消息发送到 kafka 主题,供库存服务使用

你会选择哪种方式,有什么考虑

【问题讨论】:

HTTP 太慢了 赞成,尽管我不确定这个主题是否属于这里(而不是关于编程)。我会说 Kafka 让我们以更松散的方式进行广播和连接。 【参考方案1】:

要点(对于只想要要点的人)

    Kafka - 发布和订阅(只需处理管道,工作完成后会通知)

    REST - 请求并等待响应(按需)


    Kafka - 发布一次 - 订阅 n 次(由 n 个组件)。

    REST - 请求一次,获得一次响应。交易结束。


    Kafka - 数据存储在主题中。随时来回搜索(偏移),直到主题被保留。

    REST - 一旦响应结束,它就结束了。手动使用数据库来存储处理后的数据。


    Kafka - 拆分处理,将中间数据存储在中间主题中(为了速度和容错)

    REST - 获取数据,一次性处理所有数据,或者如果您希望分解数据,请不要忘记处理您的 OWN 中间数据存储.


    Kafka - 提出请求的人通常响应不感兴趣(响应除外如果消息被发送)

    REST - 我发出请求意味着我通常期望得到响应(不仅仅是您收到请求的响应,而是对我有意义的东西,例如一些计算结果!)

问答风格

您的数据是流式传输的吗?如果数据源源不断,并且您有一个管道要执行,那么 Kafka 是最好的。

您需要请求-响应模型吗?如果用户请求某事并等待响应,那么最好使用 REST。

Kafka(或任何其他流媒体平台)通常用于管道,即我们拥有正向流数据的地方。

数据进入 Kafka,然后从那里经过 component1、 component2 等等,最后(通常)进入数据库。

为了按需获取信息,我们需要一个可以查询和获取信息的数据存储(数据库)。在这种情况下,我们提供了一个 REST 接口,用户可以调用该接口并获取他们想要的数据。


关于你的例子,

每天的供应商服务都会调用供应商 API 来获取新商品和 这些需要移动到库存服务中

问答

您的供应商 API 是否使用 REST?

然后你需要pull数据并push到Kafka。 您的库存服务(或此后的任何其他服务)将从那里订阅该主题并执行其处理逻辑。

这里的好处是您可以将需要供应商数据的任何其他服务作为消费者添加到供应商主题。

此外,即使在您的库存服务处理之后,供应商数据也始终存在。

如果您为此使用 REST,则需要为每个需要供应商数据的组件调用供应商 API,这在与 Kafka 一起使用时变得微不足道

您要查询库存吗?

通过 Kafka 处理后将其存储在数据库中,并在此之上提供 REST。这是必需的,因为 Kafka 通常是一个日志,要使数据可查询,您需要一些数据库。

【讨论】:

如果您改为比较 kafka 与响应式 rest api 会怎样?事情会改变吗?【参考方案2】:

kafka 的主要好处:

通过对每个服务的直接 REST 调用 - 如果您有 N 个服务都需要相互通信,则大约有 N^2/2 个连接。您可能还需要在一些获得大量请求的服务之前构建一些负载均衡器,并且可能需要在服务中构建一个排队/缓冲系统来排队其请求(lol)

使用 kafka,你只需要 N 个主题。根据定义,它已经提供了它的排队系统。

kafka 的主要缺点:

服务不等待请求响应。一旦响应确实出现在主题中,就很难将响应与请求关联起来。

【讨论】:

【参考方案3】:

微服务架构提倡可以独立运行的独立自主服务。让我们了解为什么我们需要消息队列?

HTTP 协议同步

人们普遍认为 HTTP 是异步的。 Http 是同步协议,但您的客户端可以异步处理它。例如。当您使用 http 调用任何服务时,您的 http 客户端将安排在后端线程(异步)上。但是,http 调用将一直等待,直到超时或响应返回,在所有这段时间内,http 调用链都在同步等待。现在,如果您一次有数百个请求,您可以想象有多少个 http 调用被同步调度,并且您可能会运行套接字。

AMQP

在微服务架构中,我们更喜欢 AMQP(高级消息队列协议)。这意味着服务将消息放入队列中并忘记它。这是真正的异步传输协议,因为一旦将消息放入队列中,您的服务就完成了,感兴趣的服务会选择这些。

这种类型的协议是首选,因为即使其他服务出现故障,您也可以毫无顾虑地扩展,因为它们最终会获得消息/事件/数据。

所以这真的取决于你的具体情况。 HTTP 很容易实现,但你不能很好地扩展它们。消息服务有自己的挑战,比如消息的顺序和工作线程,但这使得架构可扩展并且是首选方式。对于写操作总是首选队列,对于读操作,您可以使用 HTTP,但请确保您没有做一个长链,其中一个服务正在调用另一个服务并调用另一个服务。

希望有帮助!

【讨论】:

小问题,我们真的更喜欢 AMQP 用于微服务吗? Kafka 不使用 amqp,但仍然广泛用于消息传递架构;我敢肯定还有其他人在那里。正如您所提到的,我们关心消费者与生产者的解耦,我们通过消息来实现这一点,但是在谈论一般的微服务时,我们不太关心传输层的实现,比如使用的协议。 写操作更喜欢队列是有道理的,但是请求量不应该影响这个决定吗?我觉得如果只有很少的请求,那么使用队列就有点过分了.. 我会将 Kafka 替换为 Message Service Bus 。 AMQP 是开放标准的消息传递协议,它可以使用使用不同语言、框架构建的组件构建基于消息的应用程序,是的,决策可以取决于请求量,就像我说的队列用于解耦系统。这实际上取决于您的业务需求,但如果您认为系统会增长,您需要从一开始就做正确的事情。当您谈论可扩展性时,我们必须考虑传输层,例如当您使用 tcp 连接时,他们在下面使用套接字并且对其有硬限制。 如果您正在考虑可扩展的微服务架构,每一个细节都很重要。 获取请求只能使用 HTTP 进行处理。队列仅用于写操作。我们使用队列的原因是我们在微服务之间提供缓冲区,因此如果“微服务 A”为“微服务 B”丢弃消息,它将在准备好执行该操作时处理该消息。如果我们丢弃 100 条消息,而我们的微服务只能处理 10 条消息,那么消息会一直留在队列中,直到处理完毕。如果您使用的是 HTTP Post,则会向微服务 B 推送 100 条消息,系统可能会宕机。如果你想从微服务 B 获取数据,你将直接使用 Http GET。【参考方案4】:

有几篇文章可以很容易地理解 Kafka 在微服务中的作用。

microservices-apache-kafka-domain-driven-design

journey-to-event-driven

building-a-microservices-ecosystem-with-kafka

build-services-backbone-events

如果您需要任何进一步的帮助,请告诉我。很乐意提供帮助。

【讨论】:

在您看来,我们是否应该不再使用休息调用来进行微服务之间的通信?如果没有,什么时候使用 rest api 调用? 我们应该根据用例来选择,没有什么是完美和永恒的。上面的链接描述了一些用例,Kafka 是比 REST 调用更好的选择。 我已经阅读它们并且事件驱动一切都很好。但是如果订购微服务例如只需要从成员微服务中快速查找成员数据,您是否也需要使用事件驱动设计并使用 kafka发消息?

以上是关于Kafka 消息 VS REST 调用的主要内容,如果未能解决你的问题,请参考以下文章

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

使用 VS Code 中的 Auth0 为 REST API 调用调试 VUE 应用程序

RPC vs REST

《凤凰架构》-RPC vs REST

发送消息vs函数调用

确保已使用 REST 代理从 Kafka 主题读取所有消息