Kafka Streams - 是否可以在没有本地Kafka Streams实例的情况下运行远程交互式查询

时间:2017-03-10 22:19:22

标签: apache-kafka apache-kafka-streams

我有一些我想远程查询的Kafka Streams应用程序实例。

所有实例当前都在侦听指定的主机:端口对,并且每个实例都能够查询自己的本地状态存储并通过REST服务传递这些值。

+------------------+  +------------------+  +------------------+
|                  |  |                  |  |                  |
|  instance1:9191  |  |  instance2:9292  |  |  instance3:9393  |
|                  |  |                  |  |                  |
+------------------+  +------------------+  +------------------+

我想要一个单独的应用程序来查询这些实例中的状态存储:

             consumer group                         separate application
+---------------------------------------+              _____
|   [instance1] [instance2] [instance3] |  <~-------  | app |
+---------------------------------------+              -----

单独的应用程序将使用StreamsMetadataState::getAllMetadataForStore中的相同逻辑来获取应用程序正在运行的实例的所有活动主机/端口对,通过REST服务运行远程查询,并聚合内部数据它自己的应用程序逻辑。

但是,我很难实现这一点。由于主机/端口对似乎是通过使用者组协议进行通信的,因此看起来我需要实际实例化另一个Kafka Streams实例(即使用者组的另一个成员)才能利用远程交互式查询

我的问题是:

  • 是否可以在同一个使用者组中运行本地Kafka Streams实例的情况下找到应用程序的所有正在运行的实例的主机/值对? (我强调正在运行,因为我不介意实例化Kafka Streams应用程序的虚拟实例,只是为了获取主机/端口元数据,但有一个validateRunning检查可以阻止我这样做了)
  • 上述设计是否存在问题(运行单独的应用程序来查询Kafka Streams应用程序的所有实例)?也许我所谈论的行为并不受支持,因为我所做的事情会产生我尚未考虑过的分歧?

似乎应该有一个静态方法来获取状态存储元数据,这样我们就可以直接传递从构建器对象中提取的任何值。即。

KafkaStreams::getMetaDataForStore(streamsConfig, storeName);

2 个答案:

答案 0 :(得分:4)

  
      
  • 是否可以在不同时在同一个使用者组中运行本地Kafka Streams实例的情况下为应用程序的所有正在运行的实例找到主机/值对? (我强调运行,因为我不介意实例化Kafka Streams应用程序的虚拟实例只是为了获取主机/端口元数据,但有一个validateRunning检查阻止我这样做)
  •   

为什么不向您的(第一个)Kafka Streams应用程序添加新的REST API方法,该应用程序将当前活动的主机/端口对公开给您的第二个应用程序?应用程序实例当然可以随时获得这些信息。

第二个应用程序 - “单独的应用程序” - 然后可以通过此REST方法查询任何(第一个)Kafka Streams应用程序实例,以发现所有正在运行的应用程序实例。在这里,您根本不需要在第二个应用程序中运行虚拟KafkaStreams实例。

  
      
  • 上述设计是否存在问题(运行单独的应用程序来查询Kafka Streams应用程序的所有实例)?也许我正在谈论的行为不受支持,因为我正在做的事情有我尚未考虑过的分歧?
  •   

见上文。没有什么能阻止您将其他方法添加到Kafka Streams应用程序的REST层。毕竟,使用Kafka Streams API的(第一个)应用程序部分不需要是该应用程序的唯一部分。 :-)我认为你的问题可能是你的想法有点“装箱”,你觉得有必要通过Kafka Streams API在你的应用程序中做所有 - 但这是不是这样。毕竟,Kafka Streams API背后的动机之一就是让您将其与您希望在应用程序中使用的其他API和库混合使用。

答案 1 :(得分:1)

没有API支持。

建议的模式是,为所有实例添加第二个RPC(与IQ端口不同的端口,让它称之为bootstrap-port)。因此,知道一个主机/引导端口对以获取所有IQ主机/端口对的信息就足够了。

<强>更新

您还可以使用Kafka主题来传播主机/端口信息。每个实例在启动时将其主机/端口写入主题,并从那里读取此信息。棘手的部分是,从主题到期/删除。如果启用压缩,则每个实例都可以为其主机/端口消息编写逻辑删除消息。但是,如果实例崩溃,您将获得未删除的旧信息。

另一方面,您可以将此与第一种方法结合使用(即,将主机/引导程序端口而不是IQ主机/端口写入主题)。获取一个有效主机/ bootstrap-port就足够了 - 如果你使用的是无效的,你的请求会超时,你可以从查询应用程序中编写一个墓碑来清理。

结束更新

如果这也不起作用,你可以“破解”这个限制。成功重新平衡后,所有元数据都存储在主题__consumer_offsets中,理论上您可以从那里读取信息并提取所有主机/端口对。但是,您将依赖于内部实现细节,因此您的代码可能会在升级时中断。