我有一些我想远程查询的Kafka Streams应用程序实例。
所有实例当前都在侦听指定的主机:端口对,并且每个实例都能够查询自己的本地状态存储并通过REST服务传递这些值。
+------------------+ +------------------+ +------------------+
| | | | | |
| instance1:9191 | | instance2:9292 | | instance3:9393 |
| | | | | |
+------------------+ +------------------+ +------------------+
我想要一个单独的应用程序来查询这些实例中的状态存储:
consumer group separate application
+---------------------------------------+ _____
| [instance1] [instance2] [instance3] | <~------- | app |
+---------------------------------------+ -----
单独的应用程序将使用StreamsMetadataState::getAllMetadataForStore
中的相同逻辑来获取应用程序正在运行的实例的所有活动主机/端口对,通过REST服务运行远程查询,并聚合内部数据它自己的应用程序逻辑。
但是,我很难实现这一点。由于主机/端口对似乎是通过使用者组协议进行通信的,因此看起来我需要实际实例化另一个Kafka Streams实例(即使用者组的另一个成员)才能利用远程交互式查询
我的问题是:
validateRunning
检查可以阻止我这样做了)似乎应该有一个静态方法来获取状态存储元数据,这样我们就可以直接传递从构建器对象中提取的任何值。即。
KafkaStreams::getMetaDataForStore(streamsConfig, storeName);
答案 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
中,理论上您可以从那里读取信息并提取所有主机/端口对。但是,您将依赖于内部实现细节,因此您的代码可能会在升级时中断。