【问题标题】:Matching Kafka consumer and producer partition匹配Kafka消费者和生产者分区
【发布时间】:2018-02-05 02:57:36
【问题描述】:

我正在创建一个系统,其中前端服务将消息推送到 Kafka 的“请求”主题,并为一些下游后端消费者侦听另一个“响应”主题(实际上是一个最终推回 Kafka 的复杂系统)对“请求”消息进行处理并最终推送到“响应”主题。

我试图找出最优雅的方法来确保消费者在适当的分区上监听并接收响应,并且后端推送到前端消费者正在监听的分区。我们始终需要确保响应发送到产生初始消息的同一消费者。

目前我有两种解决方案,但都不是特别令人满意。任何想法或想法将不胜感激:

  1. 让每个前端决定它将侦听哪个分区并将该分区与消息一起传递给“请求”主题。后端处理完成后,会查看消息的分区成员,并推送到相应的分区。这里的一个直接问题是如何协调前端服务,以便在每个分区上均匀分布(随机分配?)。
  2. 每条消息都有一个相关 ID,一个 GUID,因此对于我们前端的每个请求,我们可以根据将 GUID 散列到分区总数来开始侦听分区,然后将消息推送到“请求”主题.然后后端将查看相关 ID 以确定要推送到的适当分区。这里的一个问题是,对于每个传入的请求,前端必须在新分区上建立一个新的消费者(这里有开销吗?)并且可能在同一个分区上有多个活动消费者以及跨多个活动消费者许多分区。
  3. 拥有一个消费者组和分区数量相等的消费者组,然后采用与(1)类似的方法,但允许 Kafka 处理哪个消费者在哪个分区上。但是接下来我们需要弄清楚当重新平衡发生时会发生什么,尤其是对于已经在后端传输的消息(因为所有分区都可能发生变化?)。

这似乎应该是一种常见的模式,所以我想知道其他人是如何解决这个问题的。

【问题讨论】:

    标签: apache-kafka kafka-consumer-api kafka-producer-api


    【解决方案1】:

    请不要使用手动分配分区的消费者。它会变得非常混乱,而且很难扩展。

    您可以使用每个前端消费者的主题来代替分区。每个前端服务都会生成一条消息,其中包含前端服务的 id 到 request 主题。然后后端使用该消息并根据该 id 生成一个响应消息到特定的unique-front-end-service-response 主题。 如果您有固定数量的前端服务,这可能是一个很好的解决方案。可能的缺点是每次要添加新的前端服务时都创建一个新主题。但是它会比手动分区分配更容易维护。

    另一种可能的解决方案是使用不同的工具。如果 Kafka 不是强制性的,请重新考虑您的要求并进行研究。可能有一个工具比 Kafka 更适合您的需求。

    【讨论】:

    • 谢谢——每个前端的单个主题似乎是一个可行的解决方案。我们在后端大量使用 Kafka,但我想我们总能找到其他方式直接与前端通信,而不是在后端处理完成后通过 Kafka。
    【解决方案2】:

    如果可以通过将 Kafka 响应消息发送到 Kafka 连接器以通过 Webhooks 直接外部传递来直接响应用户请求,则有时响应不会必须返回到原始请求应用程序、WebSocket、Email 或 SMS 文本消息返回给原始用户。

    如果您只是想做 SOAP 或 REST 风格的 RPC,那么只需使用 HTTP 而不是 Kafka,因为这是一种经过验证的模式。

    【讨论】:

    • 在我们的例子中,前端是一个 HTTP 服务,所以同一个实例需要响应我们后端返回的内容。
    • 所以以你的HTTP服务的URL为key发布Kafka请求消息。当后端 Kafka 消费者想要发送响应时,它应该使用与密钥相同的 URL 发布到响应主题。然后,用于 HTTP/webhook 的 Kafka 连接器将拾取响应消息并进行 HTTP 回传原始 HTTP 服务(可能在稍微修改的 URL 上进行响应)。因此,从原始 Web 服务的角度来看,它是 kafka 请求/http 响应。如果你想一次支持多个请求,只需在 URL 中添加一个correlationID
    【解决方案3】:

    一个优雅的方法是在后端生产者中使用分区功能,并为前端消费者使用手动分区分配assign来只监听感兴趣的分区。

    更详细:

    在前端生产者中,在向“请求”主题产生“请求”消息之前,将消息键设置为前端客户端ID(它必须是唯一的)。

    在后端消费者中,无需手动进行分区分配,只需使用subscribe订阅request主题即可。但值得注意的是,当您收到“请求”消息并对其进行处理时,请不要丢失消息密钥,保留它。因为它确定了请求的来源。

    在后端生产者中,当您完成请求过程后,您会生成一条响应消息进行回复,并将响应消息键设置为您保留在上面的前端客户端 ID。而且你还需要定义一个分区函数(一个散列函数,将一个客户端ID映射到一个分区号)。使用分区函数做send()

    在前端消费者,需要使用assgin()方法监听具体分区。但是如何知道应该监听哪个分区呢?只需使用它的 client-id(在同一个客户端上相同)和您在上面定义的相同哈希函数来计算您应该监听的分区号。

    【讨论】:

      猜你喜欢
      • 2019-10-16
      • 1970-01-01
      • 2020-08-24
      • 2019-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-07
      • 2018-02-08
      相关资源
      最近更新 更多