如何在消息驱动的微服务系统中处理基于多个事件的副作用?

时间:2018-03-16 06:54:33

标签: events apache-kafka state event-sourcing

我们目前正在消息驱动的微服务环境中工作,我们的一些消息/事件是事件源(使用Apache Kafka)。现在我们正在努力实施更复杂的业务需求,我们是否必须考虑多个事件来创建新事件和副作用。

在目前的情况下,我们正在处理可能产生错误的设备,我们已经处理过它们并且只有一个包含ERROR_OCCURRED和ERROR_RESOLVED事件的主题(所以它们按顺序排列)。我们还确保关于特定设备的所有消息始终都在同一个分区上。两条消息共享一个标识该特定错误事件的ID。我们已经有一个消费这些事件的投影,并为我们的客户提供API,s.t。他们可以看到所有发生的错误及其当前状态。

现在我们必须处理以下要求:

报告错误

我们需要一个推送系统,向外部合作伙伴报告设备错误,但仅在15分钟之后,如果在该时间范围内尚未解决。我们的第一种方法是使用所有ERROR_RESOLVED事件,存储ID并使另一个消费者以延迟的方式处理ERROR_OCCURRED事件(例如,如果其时间戳至少为15分钟,则仅消耗该主题的下一个ERROR_OCCURRED事件)。然后,我们将能够知道该特定错误是否已经解决并且不需要报告(因为它们与相应的ERROR_RESOLVED事件共享公共ID)。否则,我们会向外部合作伙伴发送HTTP请求,并在新主题上创建ERROR_REPORTED事件。 是否有更好的延迟和条件消息处理方法?

我们还必须考虑以下特殊用例:

  • 服务重启:目前我们计划将已解决的错误列表保留在内存中,因此如果服务重新启动,则必须从头开始创建该列表。我们可以重播ERROR_RESOLVED消息,但这可能需要一些时间,并且在那段时间内不应该处理ERROR_OCCURRED事件,因为这可能导致报告错误已在不到15分钟内解决,但我们只是不知道它。 有关重播与“正常”处理的良好做法吗?
  • 缩放:我们可以随时增加或减少服务实例的数量,因此分区分配可能会在运行时更改。如果我们在使用ERROR_RESOLVED事件(s.t)时为每个服务实例创建一个使用者组,那应该不是问题。每个实例都知道所有已解决的错误,同时仍然只处理其分配的分区的ERROR_OCCURRED事件(在所有实例共享的另一个使用者组中)。 是否有更好的方法来处理分区重新分配和内部状态?

提前致谢!

1 个答案:

答案 0 :(得分:0)

对于副作用,我会记录所有" side"事件存储中的操作。在您的特定示例中,当需要发送通知时,我会调用发出NOTIFICATION_SENT事件的SEND_NOTIFICATION命令。这些事件将由执行实际HTTP请求的某个工作进程处理。

实际上我会详细说明这一点,因为通知可能会失败,所以我会说,有两个事件NOTIFICATION_REQUIRED和NORIFICATION_SENT,所以我们可以重试失败的通知。

最后你的逻辑将是"如果错误在15分钟内没有得到解决并且没有发送通知 - 发送通知(或者如果它错过了时间框就丢弃)"