在X-Plane上用Elixir启动一个多人服务器

143 阅读7分钟

欢迎来到我们关于公司在生产中使用Elixir的系列案例研究。请看我们迄今为止发表的所有案例

X-Plane 11是世界上最全面、最强大的个人电脑和移动设备的飞行模拟器。X-Plane不是一个游戏,而是一个由Laminar Research创建的工程工具,可用于预测固定翼和旋转翼飞机的飞行质量,其准确性令人难以置信。X-Plane特许经营权有消费者和FAA认证的专业版本。

最近,X-Plane团队接受了增加多人游戏体验的挑战,目标是在同一会话中容纳10000名用户。这篇文章探讨了他们为什么选择Elixir,以及一个由一个开发人员组成的团队--之前没有语言经验--是如何学习语言并在6个月内部署一个广受欢迎的多人游戏体验的。整个解决方案的特点是在Elixir中对RakNet通信协议进行了全新的开源实现,并且在面临意外的负载时表现得比原来的要求更出色。

要求

X-Plane团队在模拟器中提供点对点的多人游戏已经有很长一段时间了,但从未提供过服务器托管的多人游戏。这对他们来说是一个新的旅程,他们有完全的自由来选择技术栈。根据他们的博客文章,他们的目标是。

  1. 建立一个具有错误隔离功能的坚如磐石的服务器。例如,在客户端更新时出现的异常不应导致整个服务器瘫痪。

  2. 实现一个可以扩展到数以万计的并发飞行员的单一共享世界。

  3. 快速迭代:因为这是Laminar Research团队第一次提供一个托管的多人游戏环境,他们希望能快速地推出这个系统。这将使用户能够立即开始分组飞行,并作为一个平台来衡量对进一步功能开发的兴趣。

  4. 要做到快速和一致。多人游戏有一个 "软实时 "的限制,他们需要一致和及时地服务所有客户。从数量上看,这意味着第99个百分点的响应时间比平均值或中位数重要得多。

从这些要求来看,对稳定性和快速迭代的需求排除了低级语言,即使是他们有大量内部经验的语言。

对速度和垂直可扩展性的需求排除了许多现代网络语言,如Ruby和Python,在这些语言中,扩大规模的模式通常是投入更多服务器。必须避免在多台机器上同步状态,这需要更多的开发时间,而且由于延迟增加,用户体验也会变差。

他们最终确定了三个顶级竞争者。Rust、Go和Elixir。Elixir的优势在于两个独特的功能:容错和可预测的延迟。这两点都是建立在Erlang虚拟机的核心中--Elixir运行的强大平台。领导这一实施的X-Plane的工程师Tyler Young强调。"我们想要一个可以最大限度地提高服务器容量的堆栈。我们宁愿运行一台64核的机器,而不是几十个4核的虚拟机。Saša Jurić的演讲《Erlang和Elixir的灵魂》向我们展示了平台所提供的并发模型、进程隔离和部分重启是我们正在寻找的抽象。"

用Elixir为多人游戏建模

泰勒准备试一试Elixir,他买了几本书,但很快意识到该语言的入门指南提供了他需要的背景。他解释说。"虽然入门指南涵盖了语言结构,但网站上的高级指南让你建立一个带有TCP连接的实际项目,并采用我们在生产中使用的基本架构模式。"

然而,他并没有一头扎进多人服务器,而是决定在一个较小的问题上尝试一下Elixir。他为国家海洋和大气管理局(NOAA)的天气服务编写了一个网络代理,并将其投入生产。这一经历让他认识到利用Erlang虚拟机提供的所有仪器和指标的重要性。他们选择了AppSignal来帮助消费和消化这些信息。

两周后,他开始在服务器上工作,在Elixir中实现以UDP为中心的RakNet协议。不幸的是,没有什么文档,所以他们不得不在大部分时间里参考C++的参考实现。幸运的是,得益于其在电信和网络服务领域的根基,Elixir和Erlang内置了对解析二进制数据包的支持,这使得这项任务变得很愉快。该团队还将每个UDP连接映射到Elixir中不同的轻量级执行线程,我们称之为进程。Elixir进程是廉价的、隔离的、并发的,并且由运行时公平地安排。这种设计使X-Plane团队能够充分利用鲁棒性和可预测延迟的特性,这些特性首先吸引了他们对该平台的兴趣。他们的实现是写在Erlang的gen_udp之上的,并且是开源的

在选择Elixir五个月后,他们开始欢迎测试者进入服务器。社区的反应是压倒性的积极,新的多人游戏体验导致了一个月后上线时订阅人数的大幅上升。

部署和保持简单

目前,X-Plane在北美的玩家群由一台服务器提供动力,在1台8核机器上运行,内存为16GB,尽管只有200MB或300MB的内存被有效使用。每个连接的玩家每秒发送10次更新。

对于部署,他们采用蓝绿策略,在两个相同容量的服务器之间交替进行。泰勒解释说。"我们知道Erlang虚拟机提供了热代码交换和分配,但我们尽可能地采取最简单的路线。在部署过程中,我们在两台服务器之间交替使用要容易得多,因为服务器很稳定,而且我们不经常部署。同样,当涉及到分发时,我们更倾向于纵向扩展或在不同地区为全球的玩家设立不同的服务器"。

保罗-麦卡蒂(Paul McCarty)在项目启动后加入了该项目,他可以证明其简单性。"即使之前没有Elixir的经验,我也能在早期就跳进去,为我们的HTTP APIs添加新的功能"。这些API建立在Plug之上,为他们的聊天服务提供动力,提供有关连接用户的信息,等等。他总结说。"在添加新功能时,服务器的开发永远不会成为瓶颈"。

保罗和泰勒用一个奇怪的轶事结束了我们的谈话:几个月前,他们发布了一个更新的客户端版本,其中有调试代码。这段额外的代码导致每个连接的用户每隔100ms就不断地ping服务器,即使不是在多人游戏模式下。这导致他们的流量增加了1000倍。两周后,当他们看到Elixir服务器的CPU使用率从5%上升到21%时,他们才发现这一增长。一旦他们发现了根本原因和系统的处理方式,他们就意识到他们不必急于更新客户端来删除调试代码,他们选择维持正常的发布周期。在一天结束时,这是一个完美的例子,说明他们获得了信心,并围绕语言和平台建立了信心。