如何从事件启动微服务

Posted

技术标签:

【中文标题】如何从事件启动微服务【英文标题】:How to boot up a Microservice from events 【发布时间】:2020-09-25 14:11:34 【问题描述】:

假设我有一个商店应用程序,我想对该操作进行一些复杂的验证。

    事件是我系统中唯一的事实来源。 添加产品由ProductAdded 消息表示。 负责验证产品的微服务读取消息,对其进行验证,然后生成ProductValidated 消息。

但是如果我想让微服务从零启动会发生什么? 在启动时,每条消息都被重新处理,导致对每条消费消息的验证冗余和重复。 这可以通过首先从消息队列中读取所有消息来解决,当所有消息都加载后,启动一个异步验证过程。

但是如何确保所有消息都被加载呢?也许消息的产生比从事件中构建状态的过程更快。一种解决方案可能是查询消息队列以获取给定时刻的消息总数。然后,阅读所有这些并处理它们。然后,再次查询处理。

这个问题的问题在于,在我看来,它不像是应对这一挑战的典型解决方案。我想了解在这种情况下流行的做法是什么。

【问题讨论】:

【参考方案1】:

你有几个选择:

一个 KTable,您按购物车聚合(每个购物车不能有两次相同的产品)。为了防止这种情况变得太大,需要对记录进行“墓碑化”,因此需要告诉应用程序不再有购物车。

请记住,要在 Kafka 中进行任何类型的聚合,您需要本地存储。如果您不想要或不能拥有本地存储,Kafka 是错误的工具。

我不完全理解您在下的观点,但是微服务验证过程存在问题。首先它说没有缓存或本地存储,第二点说加载所有内容(这意味着在本地存储中缓存)。

--- 编辑

您可以查看 Confluent 中对订单进行验证的示例:https://github.com/confluentinc/kafka-streams-examples/tree/5.4.1-post/src/main/java/io/confluent/examples/streams/microservices。

如果我理解正确,您可以拥有一个没有更改日志的本地存储,因此您可以在重新启动时重新填充它。

查看InventoryService.java 类,在那里你可以看到如何创建一个单独的商店。您要省略的行是 .withLoggingEnabled(),因为它会创建一个变更日志主题。

final StoreBuilder reservedStock = Stores
  .keyValueStoreBuilder(Stores.persistentKeyValueStore(RESERVED_STOCK_STORE_NAME),
    Topics.WAREHOUSE_INVENTORY.keySerde(), Serdes.Long())
builder.addStateStore(reservedStock);

您需要做的另外两件事是:

配置流以返回最早期记录config.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); 有一些代码可以在构建流之前找到存储并擦除它。查看 Confluent 的 blog post,Local State Stores 部分,其中部分说明了如何查找存储本地文件的目录,以便您可以擦除该目录。

【讨论】:

我错了。我真的应该只提到我希望它能够从零启动。 (这意味着它不会从缓存/存储中加载状态) 根据我对KTable的理解,虽然它可以提供我要求的验证,但不太适合更复杂的验证 我想把问题集中在如何将事件加载到本地存储上 我投了赞成票,但这不是我想要的答案。我正在寻找一种不基于某个流媒体平台的方法。我正在寻找理论答案

以上是关于如何从事件启动微服务的主要内容,如果未能解决你的问题,请参考以下文章

如何通过本地化事件正确实现微服务内部强一致性,事件总线跨微服务间最终一致性

微服务和 PubSub:如何确保服务使用正确的事件

大数据事件驱动的微服务架构

微服务实践:微服务的事件驱动数据管理

微服务启动

事件驱动的微服务-总体设计