如何可靠地将事件存储到 Azure CosmosDB 并恰好一次分派到事件网格

How to reliably store event to Azure CosmosDB and dispatch to Event Grid exactly once

我正在 Azure 中使用无服务器架构试验事件源/cqrs 模式。

我为事件存储选择了 Cosmos DB 文档数据库,为非规范化程序选择了 Azure 事件网格。

当事件存储在 Cosmos DB 中时,如何实现将事件可靠地传递到事件网格且恰好一次?我的意思是,如果发送到事件网格失败,它不应该存储在事件存储中,不是吗?

你不能,但无论如何也不应该这样做。也许有一些使用分布式事务的非常复杂的方法,但它们不可扩展。您不能以原子方式存储和发布事件,因为您正在写入具有不同事务边界的两个不同的持久性。您可以拥有同步 CQRS 单体,但前提是您使用相同的技术来实现事件持久性和读取模型持久性。

在 CQRS 中,应用程序分为 Write/Command 和 Read/Query 端 (this long video may help). You are trying to unify the two parts into a single one, a downgrade if you will. Instead you should treat them separately, with different models (see Domain driven design)。

写入端不应依赖于读取端的结果。这意味着,在事件存储保存事件之后,写入端就完成了。此外,写入端应包含完成其工作所需的所有数据,根据业务规则发出事件。

如果您在写入和读取部分采用不同的技术,那么您的读取端应与写入端分离,也就是说,它应该运行分开 thread/process.

实现此目的的一种方法是让 thread/process 侦听追加到事件存储、获取新事件然后将它们发布到事件网格。如果此过程失败或重新启动,它应该从中断的地方继续。我不知道 CosmosDB 是否支持这个,但是 MongoDB(也是一个文档数据库)具有 rslog,您可以 tail 在几毫秒内获取新事件。

查看 Cosmos Db 更改提要。为数据库中的每个更改内置事件 raiser/queue。您可以注册一个或多个listeners/handlers。 IE。 Azure 函数。

这可能正是您所要求的。

有人建议您可以直接进入 cosmos db 并在 changefeed 的背面附加 eventgrid。