事件驱动架构非常强大,非常适合用在分布式微服务环境中。事件驱动架构提供了解耦的架构、更容易实现的可伸缩性和更高程度的弹性。
请求应答(客户端和服务器)与事件流(发布和订阅)
但是,与请求和应答类型的架构相比,正确使用事件驱动架构要困难得多。
在过去的几年里,我们一直在逐步将我们不断增长的微服务(目前有 2300 个)从请求和应答模式迁移到事件驱动架构。下面是 Wix 工程师在实验事件驱动架构时遇到的 5 个陷阱。
这些陷阱让我们遭遇了生产事故,给我们带来了巨大痛苦,我们不得不进行重写,还得面对陡峭的学习曲线。对于每一个陷阱,我都提供了已经在 Wix 使用的经过实战验证的解决方案。
写入数据库再触发事件
(非原子操作)
我们以一个简单的电子商务流程为例(我们将在本文中使用这个示例)。
在支付处理完成后,应该更新商品库存,表示为客户保留商品。
写入数据库和产生事件是非原子操作
问题在于,将支付完成状态写入数据库,然后向 Kafka(或其他消息代理)生成“支付完成”事件并不是一个原子操作。在某些情况下,可能只有其中一个动作执行成功。
例如,数据库不可用或 Kafka 不可用可能会导致分布式系统不同部分之间的数据不一致。在这种情况下,库存可能与实际订单不一致。
原子性补救 1——Greyhound 弹性生产者
有几种方法可以缓解这个问题。在 Wix,我们使用了两种方式。第一种是使用我们自己的消息平台 Greyhound(https://github.com/wix/greyhound#greyhound),我们通过弹性生产者确保事件最终被写入 Kafka。这种缓解措施的缺点是最终可能会导致对下游事件的无序处理。Greyhound
Greyhound 生产者回退到 S3,一个将消息恢复到 Kafka 的专用服务