作者:Neil Alexander
Matrix Dendrite
Matrix[1]是建立在分布式数据结构之上的用于实时通信的联邦协议,Dendrite[2]是遵循微服务架构建立的 Matrix homeserver 的实现。它最初的目的是帮助我们克服早期单体实现中出现的一些负载问题。因此,灵活性、性能和可伸缩性一直是我们开发中关注的三个关键领域。
从 Kafka 开始
当我们第一次启动 Dendrite 项目时,我们使用 Kafka 作为在微服务组件之间分发事件和异步任务的手段。除了能够根据需要伸缩之外,我们还需要消息队列的持久性,以确保如果部分服务重新启动,不会丢失任何任务或事件。考虑到我们对部署灵活性的需求,所有微服务在单个进程下运行同样重要,因为它能够将它们分离出来,并在单独的进程下运行——甚至在不同的机器上运行。我们希望能够瞄准嵌入式和小型平台以及数据中心。
虽然 Kafka 允许我们快速获得 Dendrite 的早期版本,但我们最终发现当在完整的多体微服务部署中使用时,它相对较重,并且没有像我们希望的那样缩小规模。为了在没有独立服务器处理事件和任务的情况下在单个进程下成功运行,我们还被迫模拟了我们自己的轻量级 Kafka 风格的队列实现,这带来了额外的维护负担。我们对这两种操作模式的性能都不满意,并且发现数据保留尤其难以管理。
为什么 NATS 更适合 Dendrite
我们评估了许多不同的备选方案,最终选择了 NATS JetStream,它实际上提供了我们使用 Kafka 的所有东西,但还有许多额外的好处。首先,开始使用要容易得多。NATS 服务器消耗的系统资源少得多。由于是用 Go 编写的,我们能够将 NATS 嵌入到我们自己的单体式二进制文件中,因此在那些较小的部署中,我们甚至不需要单独的服务器实例。我们贡献了一些补丁,使得在不使用外部套接字的情况下与 NATS 服务器进行进程内通信成为可能;这使得既可以轻松定位移动设备,也可以进入 WebAssembly 下的 web 浏览器。
NATS 好处 vs. Kafka
- 消耗更少的系统资源:比 Kafka 更少的基础设施支出
- 用 Go 编写:易于嵌入,不需要像 Kafka 那样单独的服务器实例
- 更简单的数据保留:使用 JetStream,比 Kafka 更易于管理和配置保留
- 降低管理开销:比 Kafka 更方便开发人员管理和维护
- 降低代码库的复杂性:由于消除了复杂的持久存储需求,代码堆栈更加简单
对我们来说,改用 JetStream 是一种转变。整体表现优秀。我们大量使用基于兴趣的保留策略,以确保工作完成后得到清理。我们利用能够手动确认项目的优势,以确保它们在清理之前被成功处理。我们已经能够成功地管理来自 NATS 流的工人池,并在许多不再需要自己的持久存储的地方大大降低了我们代码库的复杂性。作为我们点对点演示的一部分,我们甚至在 iOS 和 Android 上的应用嵌入式场景中成功运行了它。
总之,我们的团队一直在寻找合适的工具和架构,以满足用户对性能和灵活性的需求。作为我们进化的一部分,我们从 Kafka 转向 NATS,并且没有回头。请继续关注 Dendrite 明年有哪些有趣的更新!
关于作者
Neil Alexander 是一名软件开发人员,在Element[3]从事Matrix(以及 Dendrite)[4] 方面的工作。他对安全、隐私、分散系统和计算机网络感兴趣。Neil 还拥有终端用户计算和企业级系统架构方面经验。
参考资料
[1]
Matrix: https://matrix.org/
[2]
Dendrite: https://github.com/matrix-org/dendrite
[3]
Element: https://element.io/
[4]
Matrix(以及 Dendrite): https://matrix.org/