几天以来,我一直在试图弄清楚如何通知其他微服务在微服务 A 中创建了一个新实体,该微服务 A 将该实体存储在 MongoDB 中。
我想要:
微服务之间的耦合度低
避免微服务之间的分布式事务,如两阶段提交 (2PC)
起初,像 RabbitMQ 这样的消息代理似乎是完成这项工作的好工具,但后来我发现在 MongoDB 中提交新文档并在代理中发布消息不是原子的问题。
为什么是事件溯源?通过 eventuate.io:
解决此问题的一种方法是通过添加一个标记来说明文档是否已在代理中发布并具有计划的后台进程来搜索 MongoDB 中未发布的文档并将其发布到代理,从而使文档的架构变得更脏确认,当确认到达时,文档将被标记为已发布(使用至少一次和幂等语义)。在这个和这个答案中提出了这个解决方案。
阅读 Chris Richardson 的《微服务简介》后,我在这篇关于使用事件溯源开发功能域模型的精彩演讲中结束了其中一张幻灯片问道:
如何在没有 2PC 的情况下原子更新数据库并发布事件和发布事件?(双写问题)。
答案很简单(在下一张幻灯片上)
更新数据库并发布事件
这是基于CQRS a la Greg Young的另一种方法。
域存储库负责发布事件,这通常在单个事务中,同时将事件存储在事件存储中。
我认为将存储和发布事件的责任委托给事件存储是一件好事,因为它避免了 2PC 或后台进程的需要。
然而,从某种意义上说,这是真的:
如果您依赖事件存储来发布事件,那么您将与存储机制紧密耦合。
但是,如果我们采用消息代理来实现微服务之间的通信,我们也可以这么说。
更让我担心的是,事件存储似乎变成了单点故障。
如果我们从eventuate.io看这个例子
我们可以看到,如果事件存储关闭,我们就无法创建账户或转账,失去了微服务的优势之一。(尽管系统将继续响应查询)。
那么,确认最终示例中使用的事件存储是单点故障是否正确?