简单、省钱、个月入:Playtomic由.NET改用Node和Heroku

2012 年 10 月 21 日5770

【51CTO快译】Playtomic是一项游戏分析服务,这项服务应用于每天大约2000万人在玩的约8000个手机游戏、互联网游戏和可下载游戏。

下面是Playtomic首席执行官Ben Lowry接受Hacker News采访时给出的精辟总结:

昨天就有超过2000万的人点击了我的API,点击次数达700749252人次,在玩大约8000个采用我那个分析平台的游戏,玩游戏的时间加起来总共将近600年。这只是昨天的情况。许多不同的瓶颈摆在从事大规模运营的人的面前,有待克服。就我的使用情况而言,Heroku和NodeJS最终克服了一大堆瓶颈,而且成本非常低。

Playtomic一开始几乎完全采用了微软.NET和Windows架构,这套架构运行了3年,后来被换成了使用NodeJS全面改写的架构。在使用期间,整个平台从原来一台服务器上的共享空间,扩展到一台完全专用的服务器,后来扩展到第二台专用服务器,随后API服务器被卸载到一家虚拟专用服务器(VPS)提供商,再后来扩展到四六家相当大的VPS。最后,API服务器选用了Hivelocity的8台专用服务器,每台专用服务器搭载采用超线程技术的八核处理器、8GB内存以及运行API堆栈3个或4个实例的双500GB磁盘。

这些服务器经常同时服务于30000至60000个游戏玩家,每秒收到的请求多达1500个,通过DNS轮询技术(DNS round robin),实现负载均衡机制。

今年7月份,整批服务器被换成了使用NodeJS改写的服务器,这些服务器托管在Heroku处,节省了大笔费用。

借助NodeJS扩展Playtomic

迁移过程涉及两个部分

1.专门使用平台即服务(PaaS):PaaS的优势包括:价格低、使用方便、可以利用提供商的负载均衡机制以及降低总的复杂性。缺点包括:NodeJS没有New Relic应用性能管理工具,崩溃处理起来很棘手,以及平台总体上欠成熟。

2.由.NET改用NodeJS:原来的架构是ASP.NET / C#,带本地MongoDB实例,一项服务在本地预处理事件数据,并发送至集中式服务器有待完成,改为Heroku + Redis上的NodeJS以及SoftLayer上的预处理(参阅Catalyst程序)。

专门使用PaaS

降低复杂性方面成效显著。我们有8台专用服务器,每台服务器在我们的托管合作伙伴Hivelocity运行API的3个或4个实例。每台服务器运行一小组软件,包括:

■MongoDB实例

■日志预处理服务

■监控服务

■API站点的IIS

通过FTP脚本来完成部署工作,该脚本将新的API站点版本上传到了所有服务器。服务部署起来比较烦人,不过不常变化。

说到日志数据被预处理并发送之前先暂时存起来,MongoDB是个差强人意的选择。虽然它在速度方面提供了巨大优势:起初只要写入到内存,这意味着写入请求几乎立即被“完成”——这比Windows上的常用消息队列出色得多,但是根本无法收回已删除数据留下的空间;这意味着,要是不经常加以压缩,数据库大小会迅速增加到100GB以上。

PaaS提供商的优势相当显而易见,它们似乎都很相似,不过Heroku和Salesforce最让人放心,因为它们似乎是最成熟的,而且得到了广泛的技术支持。

迁移到PaaS面临的主要挑战在于改变这个观念:我们可以让辅助软件连同网站一起运行,就像之前在专用服务器上那样。大多数平台提供了你可以充分利用的某种background worker线程,但是这意味着你要通过第三方服务或看似没有必要的服务器,传送来自万维网线程的数据和任务。

我们最终选择了Softlayer处的一台大型服务器,它运行十几个专用的Redis实例和一些中间件,而不是background worker。Heroku并不针对出站带宽收费,Softlayer并不针对入站带宽收费,这有效地避免了所需的大量带宽。

由.NET改用NodeJS

在服务器端处理JavaScript是个有利也有弊的过程。一方面,不用拘泥形式和没有样板带来了自由。而另一方面,没有New Relic管理工具,也没有编译错误,这就加大了各方面的难度。

两个主要的优势让NodeJS特别适用于我们的API。

1. background worker与Web服务器在同一个线程和内存中。

2.与Redis和MongoDB建立起了持久式、共享式的连接。

Background worker

NodeJS有这项非常有用的功能:可以独立于请求而继续工作,这样你可以预取数据及其他操作,让你可以很早终止请求,然后完成处理请求的任务。

对我们来说特别有优势的地方是,可以在内存中复制整批的MongoDB集合,定期刷新,那样全部的工作类都可以访问目前数据,没必要用到外部数据库或本地/共享缓存层。

我们在下列方面使用这项功能,每秒可以少接受100次至1000次的数据库查询:

■主API上的游戏配置数据

■数据导入API上的API证书

■开发人员用来存储配置或其他数据、热装入到游戏中的GameVars功能

■游戏积分榜(Leaderboard)积分表(不包括积分)

基本模式如下:

其优势在于每个dyno或实例而不是每个用户有一条通道连接至你的后端数据库,还有速度非常快的本地内存缓存总是存有新数据。dyno是在Heroku上运行的单一Web进程,它每次能够服务于一次Web请求(网页浏览)。

要注意的地方是,你的数据集必须很小,这与其他数据都在同一个线程上操作,所以你要注意,尽量避免堵塞线程或处理过于繁重的处理器工作。

持久性连接

对我们的API而言,NodeJS较之.NET的另一大好处是持久性数据库连接。使用.NET来连接的传统方法是,打开你的连接,进行操作,之后你的连接返回到连接池,以便马上重复使用,或者如果不再需要,就过期作废。

这很常见;除非你遇到并发性很高的环境,否则它完全可行。在并发性很高的环境下,连接池无法足够快地重新使用连接,这意味着它会生成新的连接,而数据库服务器就不得不扩展,以便处理这些新连接。

在Playtomic,我们通常同时有几十万个游戏玩家在发送事件数据,这些事件数据需要推送回到我们在一个不同数据中心的Redis实例;如果使用.NET,那就需要建立大量的连接——这就是为什么我们当初在每一台旧的专用服务器上本地运行MongoDB。

借助NodeJS,我们每个dyno/实例就有一个连接,负责推送某个dyno收到的所有事件数据。它不依赖诸如此类的请求模式:

最后结果

高负载:

上一分钟的请求:

这些数据来自在后台运行的针对每个实例的某种负载监控系统,把计数器推送到Redis,然后它们被汇集起来,存储在MongoDB中,你可以在https://api.playtomic.com/load.html看到实际过程。

该数据有几种不同类别的请求:

■事件,检查来自MongoDB的游戏配置、执行GeoOP查询(采用了非常快的开源实现方式,详见https://github.com/benlowry/node-geoip-native),然后推送至Redis。

■GameVars、积分榜和玩家关卡都检查来自MongoDB的游戏配置,然后检查任何相关的MongoDB数据库。

■数据查询被代理给Windows服务器,那是由于NodeJS对存储过程的支持很糟糕。

结果是100000个并发用户给Redis带来的负载特别轻,每分钟有500000次至700000次lpush(在另一端被取出来)。

就每分钟1800至2500次创建、读取、更新和删除(CRUD)而言,这是非常轻的MongoDB负载:

原文链接:http://http://www.zjjv.com///blog/2012/10/15/simpler-cheaper-faster-playtomics-move-from-net-to-node-and.htm

【编辑推荐】

【责任编辑:黄丹 TEL:(010)68476606】

原文:简单、省钱、个月入:Playtomic由.NET改用Node和Heroku 返回操作系统首页

0 0