apache-kafka - Kafka 流和 RPC : is calling REST service in map() operator considered an anti-pattern?

标签 apache-kafka apache-kafka-streams

实现使用引用数据丰富存储在 Kafka 中的传入事件流的用例的简单方法是调用 map()运算符(operator)为每个传入事件提供此引用数据的外部服务 REST API。

eventStream.map((key, event) -> /* query the external service here, then return the enriched event */)

另一种方法是使用带有引用数据的第二个事件流并将其存储在 KTable 中。这将是一个轻量级的嵌入式“数据库”,然后将其加入主要事件流。
KStream<String, Object> eventStream = builder.stream(..., "event-topic");
KTable<String, Object> referenceDataTable = builder.table(..., "reference-data-topic");
KTable<String, Object> enrichedEventStream = eventStream 
    .leftJoin(referenceDataTable , (event, referenceData) -> /* return the enriched event */)
    .map((key, enrichedEvent) -> new KeyValue<>(/* new key */, enrichedEvent)
    .to("enriched-event-topic", ...);

“天真”的方法可以被认为是一种反模式吗?可以推荐“KTable”方法作为首选方法吗?

Kafka 每分钟可以轻松管理数百万条消息。从 map() 调用的服务运算符(operator)也应该能够处理高负载并且具有高可用性。这些是服务实现的额外要求。但是如果服务满足这些标准,可以使用“天真”的方法吗?

最佳答案

是的,在map()之类的Kafka Streams操作里面做RPC是可以的手术。您只需要了解这样做的利弊,请参见下文。此外,您应该从您的操作中同步执行任何此类 RPC 调用(我不会在这里详细说明原因;​​如果需要,我建议创建一个新问题)。

从 Kafka Streams 操作中执行 RPC 调用的优点:

  • 您的应用程序将更容易适应现有架构,例如一种普遍使用 REST API 和请求/响应范式的地方。这意味着您可以在第一个概念验证或 MVP 方面快速取得更多进展。
  • 根据我的经验,这种方法对于许多开发人员(尤其是那些刚开始使用 Kafka 的开发人员)来说更容易理解,因为他们熟悉在过去的项目中以这种方式进行 RPC 调用。思考:它有助于从请求-响应架构逐渐转向事件驱动架构(由 Kafka 提供支持)。
  • 没有什么可以阻止您从 RPC 调用和请求响应开始,然后迁移到更符合 Kafka 习惯的方法。

  • 缺点:
  • 您将 Kafka Streams 驱动的应用程序的可用性、可扩展性和延迟/吞吐量与您正在调用的 RPC 服务的可用性、可扩展性和延迟/吞吐量耦合。这也与考虑 SLA 相关。
  • 与上一点相关,Kafka 和 Kafka Streams 的扩展性非常好。如果您正在大规模运行,您的 Kafka Streams 应用程序可能最终会对您的 RPC 服务进行 DDoS 攻击,因为后者可能无法像 Kafka 那样扩展。您应该能够很容易地判断这在实践中是否对您来说是个问题。
  • RPC 调用(例如来自 map() 内的)是一种副作用,因此是 Kafka Streams 的黑匣子。 Kafka Streams 的处理保证不会扩展到此类副作用。
  • 示例:Kafka Streams(默认情况下)基于事件时间(=基于事件在现实世界中发生的时间)处理数据,因此您可以轻松地重新处理旧数据,并且仍然得到与旧数据相同的结果还是新的。但是您在此类重新处理期间调用的 RPC 服务可能会返回与“当时”不同的响应。确保后者是您的责任。
  • 示例:在失败的情况下,Kafka Streams 将重试操作,即使在这种情况下,它也将保证只处理一次(如果启用)。但它本身并不能保证您正在从 map() 内部执行 RPC 调用。将是幂等的。确保后者是您的责任。

  • 替代品

    如果您想知道还有哪些其他选择:例如,如果您正在执行 RPC 调用来查找数据(例如,使用侧/上下文信息来丰富传入的事件流),您可以通过使直接在 Kafka 中查找可用的数据。如果查找数据在 MySQL 中,您可以设置一个 Kafka 连接器来持续将 MySQL 数据摄取到 Kafka 主题中(想想:CDC)。在 Kafka Streams 中,您可以将查找数据读入 KTable并通过流表连接执行输入流的丰富。

    关于apache-kafka - Kafka 流和 RPC : is calling REST service in map() operator considered an anti-pattern?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49757709/

    相关文章:

    apache-kafka - Kafka 机架 ID 和最小同步副本数

    apache-kafka - Kafka 文件流

    apache-kafka - Kafka Streams KTable Store 在这种情况下对于压缩输入主题没有用,替代方案?

    apache-kafka - 带有自定义时间戳的 Kafka Connect.extractor

    apache-kafka - 与 Kafka 流的连接断开时 KafkaProducer 的行为

    java - 如何使用 kafka 轮询远程目录中的新文件

    apache-kafka - 验证 kafka 主题消息

    apache-kafka - 重新分区时的 Kafka Streams 线程数

    apache-kafka - 无论如何,对于kafka Streams应用程序中的不同输入主题,是否可以使用不同的 auto.offset.reset 策略?

    java - 具有 Avro 记录的 Kafka Streams TopologyTestDriver 的架构注册问题