在不和谐时使用长生不老药进行大规模实时通信

2020-10-15 22:27:43

欢迎收看我们关于公司在生产中使用长生不老药的系列案例研究。单击此处查看我们到目前为止发布的所有案例。

“不和谐”由杰森·西特伦和斯坦·维什涅夫斯基于2015年创立,是一个永久的、仅限受邀的社区和朋友空间,人们可以在这里根据自己想要的交谈方式在语音、视频和文本之间跳跃,让他们以非常自然或真实的方式进行对话。今天,这项服务在全球拥有超过1亿的月度活跃用户。每天,人们在670万台活动服务器/社区的不一致服务器上花费40亿分钟进行对话。

从第一天起,Discord就将长生不老药作为其聊天基础设施的主干。当Discord第一次采用这种语言时,他们还在努力建立一家可行的企业,面前摆着许多问题和挑战。长生不老药在给他们提供所需的技术灵活性以发展公司方面发挥了关键作用,也成为了使他们的系统能够大规模运行的基石。

早在2015年,Discorde就选择了两种主要语言来构建他们的基础设施:Elxir和Python。最初选择elixir为WebSocket网关提供支持,负责中继消息和实时复制,而Python为他们的API提供支持。

现在,Python API是一个整体,而Elixir堆栈包含大约20个不同的服务。这些架构选择并不代表语言之间的二分法,而是一个务实的决定。来自Discorde团队的Mark Smith简洁地解释道:“考虑到Elixir服务将处理更大的流量,我们设计它们的方式是我们可以单独扩展每个服务。”

在此过程中,Discord还探索了其他技术,Go和Rust就是两个例子,结果截然不同。虽然不和谐围棋在一次短暂的进攻后就完全被淘汰了,但铁锈已经被证明是他们工具箱中的一个极好的补充,因为它能够很好地玩药剂和蟒蛇。

在并发处理数百万连接的用户时,有效的通信起着至关重要的作用。客观地说,一些最受欢迎的服务器,比如专为堡垒之夜和“我的世界”服务的服务器,已经接近60万用户。在给定时刻,在这些服务器中遇到超过20万活动用户的可能性不小。如果有人更改了用户名,Discorde必须将此更改广播给所有连接的用户。

总体而言,“不和谐”的沟通数量令人印象深刻。他们已经跨越所有服务器超过1200万并发用户,每秒向客户端发送超过2600万个WebSocket事件,而这一切都是由Elixir提供支持的。

就实时通信而言,Erlang VM是这项工作的最佳工具。

当我们问他们的团队“为什么要吃灵丹妙药?”时,杰克·海因茨给出了一个直截了当的回答:“就实时通信而言,Erlang VM是最适合这项工作的工具。它是一个用途非常广泛的运行时,具有用于构建分布式系统的优秀工具和推理。“。从技术上讲,这种语言是一种天然的契合。然而,早在2015年,Elixir仍然是一个赌注:“Elixir v1.0刚刚问世,所以我们不确定语言会朝哪个方向发展。对我们来说,幸运的是,我们对这种语言的演变和社区的形成感到高兴。“。

为了给他们的聊天消息系统提供动力,Discorde运行着一个拥有400-500台Elixir机器的集群。也许,最令人印象深刻的壮举是,Discorde的聊天基础设施团队由5名工程师组成。没错:5名工程师负责20多个Elixir服务,能够处理数百万并发用户,每秒推送数千万条消息。

Discorde还使用Elixir作为其音频和视频服务的控制平面,也称为信令,在用户之间建立通信。然后,C++负责媒体流,这一组合总共运行在1000多个节点上。

Elixir服务使用分布式Erlang(作为Erlang虚拟机的一部分提供的通信协议)在它们之间通信。默认情况下,分布式Erlang构建一个全网状网络,但是您也可以通过设置适当命名的-CONNECT_ALL FALSE标志,要求Erlang VM将勾勒拓扑的工作留给您。Discorde团队设置此选项以组装部分网状网络,其中ETCD负责服务发现和托管共享配置。

聊天基础设施开发人员并不是唯一接触到Elixir代码库的人。根据马克·史密斯(Mark Smith)的说法,这是不和谐文化的重要组成部分:“我们不是在竖井里工作。因此,Python开发人员在构建新功能时可能必须使用Elixir服务。我们将一起制定功能规范,找出可伸缩性要求,然后他们将处理Pull请求,我们将审查并帮助他们迭代该请求。“。

要以这样的规模运行,Discorde学会了如何利用Erlang VM的能力、它的社区,以及何时认识到需要他们找到自己的解决方案的挑战。

例如,Discorde使用牛仔处理WebSocket连接和TCP服务器。为了管理数据突发并提供负载调节,例如背压和减负,他们使用GenStage,这一点他们在过去已经详细讨论过了。

其他时候,公司和社区的努力是齐头并进的。当Discorde使用Rustler项目来扩展到1100万并发用户时就是这种情况,该项目在Elixir和Rust之间提供了一座安全的桥梁。他们使用Rustler将Rust中内置的自定义数据结构直接连接到他们的Elixir服务中。

然而,团队已经非常清楚地表明,动力源泉是Erlang平台。每次他们不得不推动他们的堆栈前进时,他们都不会感到被技术逼到了绝境。恰恰相反,他们的工程师总是可以构建高效的解决方案,以不协调的规模运行,通常只需几百行代码。不和谐经常会将这些项目返还给社区,就像在Manifold和ZenMonitor中看到的那样。

当事情出错时,不和谐团队也很快适应了。例如,他们两次尝试在生产中使用Mnesia-作为Erlang标准库的一部分提供的数据库。他们在持久模式和内存模式下尝试了Mnesia,数据库节点在故障情况下经常会落后,有时甚至无法赶上。最终,他们完全抛弃了Mnesia,使用Erlang的内置构造(如GenServer和ETS)构建了所需的功能。如今,它们可以在2-3秒内解决这些相同的故障情况。

在加入公司之前,聊天基础设施工程师中没有一个人有使用Elixir的经验。他们都是在工作中学到的。团队成员马特·诺瓦克(Matt Nowack)和戴西·周报告说,最初他们很难理解他们所有的服务是如何沟通的。Matt补充道:“一开始,很难接受Erlang VM提供的所有保证。我担心不可能发生的数据竞争和并发问题。“。最终,他们将这些保证放在心上,发现自己的工作效率更高,更有能力依赖平台及其工具。Matt继续说:“Erlang VM提供的自省工具是同类中最好的。我们可以查看集群中的任何VM进程并查看其消息队列。我们可以使用远程shell连接到任何节点并调试实时系统。所有这些都给我们带来了无数次的帮助。“。

在不一致的规模上运行会为掌握语言增加自己的维度,因为他们需要熟悉提供并发性、分布性和容错性的抽象。如今,诸如NeXen和Phoenix这样的框架可以为开发人员处理这些问题,但是底层的构建块始终可供工程师组装他们自己的堆栈,例如Discorde团队。

最后,杰克总结了长生不老药和Erlang VM之间的不和是多么重要,以及它是如何影响他个人的:“没有长生不老药,我们在不和谐中所做的事情是不可能的。这在Node或Python中是不可能的。如果它是一个C++代码库,我们不能用五个工程师来构建它。学习灵丹妙药从根本上改变了我对软件的思考和推理方式。它给了我新的洞察力和解决问题的新方法。“