• Feeds

  • Posts Tagged ‘网游服务器’


    FarmVille(美版开心农场)谈架构:所有模块都是一个可降级的服务


    在2009年Facebook Developer Garage Shanghai活动上,Five Minutes程延辉 介绍开心农场架构,让大家了解了SNS game的一些挑战和设计模式。

    由于农场游戏风靡全球,最近highscalability.com网站采访了美版开心农场FarmVille的Luke Rajlich,他介绍了FarmVille的部分架构资料(1)。

    所有模块都是一个可降级的服务

    For any web application, high latency kills your app and highly variable latency eventually kills your app.

    由于大型的网络应用需要依赖各种底层及内部服务,但是服务调用的高延迟是各种应用的最大问题,在竞争激烈的SNS app领域更是如此。解决此问题的方法是将所有的模块设计成一种可降级的服务,包括Memcache, Database, REST API等。将所有可能会发生大延迟的服务进行隔离。这可以通过控制调用超时时间来控制,另外还可以通过应用中的一些开关来关闭某些某些功能避免服务降级造成的影响。

    上面这点我也有一些教训,曾碰到过由于依赖的一些模块阻塞造成服务不稳定的现象。

    1. 某Socket Server使用了ThreadPool来处理所有核心业务。
    2. 不少业务需要访问内网的一个远程的User Service(RPC)来获取用户信息。
    3. User Service需要访问数据库。
    4. 数据库有时候会变慢,一些大查询需要10秒以上才能完成。

    结果4造成3很多调用很久才能执行完,3造成2的RPC调用阻塞,2造成1的ThreadPool堵塞,ThreadPool不断有新任务加入,但是老的任务迟迟不能完成。因此对于最终用户的表现是很多请求没有响应。部分用户认为是网络原因会手工重复提交请求,这样会造成状况并进一步恶化。上面的问题根本是没有意识到远程服务可能会超时或失败,把远程服务RPC调用当成一个本地调用来执行。

    解决思路一:RPC增加Timeout
    解决思路二:将RPC改成异步调用。

    另一分布式大牛James Hamilton谈到(2)上面这种做法就是他论文Designing and Deploying Internet-Scale Services中的graceful degradation mode(优雅降级)。

    FarmVille其他数据

    • FarmVille基于LAMP架构,运行在EC2上。
    • 读写比例是3:1。
    • 使用开源工具来做运维监控,如nagios报警,munin监控,puppet配置。另外还开发了很多内部的程序来监控Facebook DB, Memcache等。
    • 到Facebook接口的流量峰值达到3Gb/s,同时内部的cache还承担了1.5Gb/s。
    • 另外可动态调整到Facebook与Cache之间的流量,Facebook接口变慢时,可以利用cache数据直接返回,终极目的是不管发生了那个环节的故障,能够让用户继续游戏。

    小结

    尽管FarmVille公布了上面一些技术资料,凭借上面这些资料无法全部了解FarmVille的架构。但是所有模块都是一个可降级服务的概念值得设计大规模应用的同行参考。

    Resource

    1. How FarmVille Scales to Harvest 75 Million Players a Month
    2. Scaling FarmVille

    陈杰谈网游服务器的后端技术

    在12/20的Erlang开发者大会上,西山居的陈杰(bitcowboy)的演讲《网游服务端寻路》给我的印象非常深刻。他通过一个网游服务器寻路的案例,给大家讲述了在算法,架构,cache,并发编程及借鉴了Erlang的一些先进思路的各种经验及体会。

    • 算法,运营对寻路的要求比普通算法性能要高100倍。2D/3D中分别如何设计算法达到性能要求。
    • 稳定性
    1. 将独立的模块封装成单独的进程。
    2. 进程间通讯(IPC)使用TCP,为什么使用TCP而不是其他更高效的本地IPC方式?一方面因为大部分项目都有现成稳定的TCP模块,另外一方面更容易将一台服务器拆分到多个服务器,程序完全不用修改。
    3. 进程死掉怎么办?进程调用长时间不返回怎么办?
    4. 面对3的问题,旁边有另外一游戏架构设计师更是提到他们采取更激进的做法,将所有的进程做成单任务式的,完成任务就结束。分配任务线程为每个任务开新进程。有点象用Erlang中的process或Java中线程池的做法。
    • 一种多进程访问共享内存不需要加锁的设计模式,如图所示。

    调度进程

    (Figure: 来源陈杰PPT, 作者为陈杰)

    1. 调度进程给寻路进程分配任务,每次一个任务。
    2. 寻路进程更新cache为了避免并发访问,先只写入到 local cache
    3. 如果所有寻路进程空闲,调度进程会通知其中1个寻路进程将local cache同步到全局cache
    4. 如果一个寻路进程指定的时间没有返回,可简单kill之
    5. 此模式适合更多使用场合
    • 一种热升级模块的设计模式,简述:新进程使用新端口启用->通知调度启用新端口->调度程序将请求转向新端口->老模块完成手头工作后,被调度告知自动结束。

    总的说来,陈杰的演讲反应非常热烈,旁听参与的听众讨论也非常热烈,因为本人不是演讲者,很多细节没法在这里深入表达,PPT中也只是表达了现场的部分观点。

    另外这个演讲是以一个小组讨论的形式进行的,这样演讲者和听众的思路非常自由,比单独站台上讲相比可以进行更深入的交流。所以陈杰总是提醒大家,我们还是把这个演讲稿先讲完吧。

    对,我们也先把演讲稿看完把,Google Docs 在线预览版:网游服务端寻路