使用 kafka 和键值存储的请求-响应

Request-response with kafka and key-value store

TLDR:有一个 request/response 模式。当前请求通过 activemq 队列完成,响应通过 memcached 键值存储(由前端轮询)完成。由于各种原因想迁移到kafka,想知道我们是否可以重新构建响应路径以不使用memcached。

我试图了解以下问题的最佳实践系统设计。

我们有一个前端生成需要大量处理的请求。该应用程序需要响应才能前进。有时我们需要 undo/step 返回(这会让你回到之前的状态)。有一组后端可以执行繁重的处理步骤。

在我们当前的设置中,前端将请求推送到队列(当前为 activemq),后端尽可能地处理队列中的项目,并将结果存储在键值存储(memcached)中,键是 UUID来自队列的消息(它本身是一个唯一的会话 ID + 非唯一的步骤 ID)。前端正在轮询商店以获取消息的 UUID。这样做的好处是前端可能会丢失 connection/etc 但只要保留会话 ID,我们就可以 ping 键值存储以获得我们需要的结果。我们偶尔也需要移动 back/undo 个操作,我们可以在键值存储中返回结果(因为每个步骤都有自己的 UUID,并且所有 UUID 都是已知的)。

但是,将来我们希望能够至少部分地通过队列进行响应,这样我们就可以拥有一些分析工具作为请求和响应的消费者。 "minimal-change" 将让响应生产者推入队列并让 memcached 成为消费者之一。但也许有更好的方法。我们也在考虑从 activemq 切换到 Kafka,因为这会给我们带来可重玩性(但我们没有使用 kafka 的经验)。

看看 Kafka,它看起来像获取特定消息需要扫描整个分区,是否有更简单的方法来检索特定消息?我们是否为每个交互序列生成一个主题?如果我们想重播但不知道偏移量,我们的资源是什么(除了查看非常多的消息)?我们的负载非常小(约 100 万 messages/day)所以我想一切都可行,但最佳实践是什么(臭名昭著的,如果我们扩展会怎样)?

据我了解您的用例,您没有通过推送将响应传递给应用程序的有效方法,这就是为什么您让应用程序可以通过 id(密钥)提取响应。您可以关闭各种组件,例如Kafka 的 ActiveMQ,任何其他 KV 存储的 memcached,但最终如果你的限制是应用程序需要从服务器拉取结果,你将始终必须使用异步传输的响应并使它们在服务器上可用.例如,如果您切换到 Kafka,您可以将您的消费者实现为 Kafka Streams 中的 [global] KTable 并以这种方式提供响应,但这仍然只是一个具有额外步骤的 KV 存储。没有直接从 Kafka 主题获取特定 message/offset 的好方法,这不是它真正打算使用的方式。

在不知道更多细节的情况下,将异步传​​输组件(ActiveMQ、Kakfa 等)与服务组件分开似乎是明智的,以便能够单独扩展或交换它们。例如,如果您扩展到不再适合单个 memcached 实例的内存的大小,您可以直接迁移到任意数量的分布式 KV 存储,如 Redis、Couchbase、DynamoDB 等。