Node.js之网游服务器实践

此文已由做者尧飘海受权网易云社区发布。
web

欢迎访问网易云社区,了解更多网易技术产品运营经验。编程


随着Node.js的不断发展与壮大,应用范围也愈来愈普遍,从传统的企业应用,到互联网使用,再到云计算的发展,它的身影也是随处可见。固然,它的受欢迎程度能在短期内获得这么快的发展,除却与其自己的事件模型及V8的性能优化等一系列特性有关以外,还和国内外不少互联网公司的攻城师的大量应用和参与到开源项目中有密切关系,如网易的游戏开发,淘宝的数据之美等等。随着HTML5应用和移动互联网平台的指数增加,愈来愈多的用户使用了移动平台的休闲服务,采用 Node.js 实现高性能和可扩展性的游戏服务将是一件有意义的工做。缓存

在互联网上,目前有一些采用 Node.js 实现的开源游戏服务框架,如 Mozilla Browser Quest Google Grits Chilly等。可是无一例外,这些框架不但与游戏逻辑联系紧密,并且几乎没有可扩展性和性能数据,同时也不提供任何游戏开发的管理工具,除了采用 JavaScript 编写外,很难体现出采用 Node.js 实现游戏开发的优越性。安全

概念

一般游戏分为角色扮演类和策略类及混合类等几种游戏类型。那么在网页游戏类型中,根据游戏的类型,开发者可能采用不一样的架构实现方式,如策略类游戏可能更偏重于游戏的策略性和逻辑性,也就是考验游戏玩家的各类组合或搭配之类的游戏,对实时性的要求不会很高,在用户的可接受范围以内便可,所以也能够采用经常使用的Web应用开发模式来实现,而客户端采用轮询或长链接等方式来实现,这些应用模式也有不少的相关经验能够参考,所以能作到具备较好的可扩展性及伸缩性;此外,应用服务器和服务框架等也能够采用现存的技术实现,可是这只能知足对游戏实时性要求不高的场景服务,因为此类的应用方案很是成熟,在下文的讨论中,将再也不详述。性能优化

角色扮演类游戏根据策划的要求能够实现各类各样的功能,如聊天,打斗,自动刷怪等各类复杂的功能,可是开发者基本能够把这些功能抽象地划分为二大类,即服务端的网络传输与逻辑运算能力,这样游戏服务的开发和实现会稍微简单些。如今,网络的实时传输基本上是采用Socket服务器来实现的,逻辑运算这个就不须要再述了,所以,游戏服务器就能够粗略的概括为Socket的服务器综合游戏业务逻辑的实现。服务器

Web应用区别

从上面游戏服务的概念简单介绍中能够得知,实时游戏服务器的开发与传统的Web开发仍是具备一些不一样点,这些不一样点着重体如今如下几个方面:
大部分的Web应用仍是短链接的方式去实现,而游戏的实时性须要采用长链接的方式进行。websocket

Web应用的场景通常是读多写少的应用,热点数据基本能够缓存;游戏服务的数据常常发生变更,如移动中的路径,打怪掉血等,缓存基本很快就失效,属于写多读少的应用场景。网络

广播特性,即Web应用行为上基本只须要用户与服务器交互,其余用户要实现共享他人信息的时候,会采用相似拉的方式如长轮询来实现数据交互,即便在没有数据更新的状态时也须要消耗必定的服务端资源,形成必定的浪费;游戏里面的交互方式须要实时进行,对影响三方的数据,必须采用广播的方法进行消息推送,即推的模式。架构

目前的Web应用开发通常采用无状态性的方式来实现,所以能够实现较好的可扩展性,不少Web服务会采用绑定会话或集中会话等方式工做,当后面的某台服务器出现宕机时,服务也能够很快的切换;可是游戏服务器和用户之间的链接是有状态的,在断开时须要进行相关的通知和数据持久化,在重连时须要进行状态恢复等手段来维护游戏世界的运行。app

除以上几点不一样以外,还有负载均衡的策略,服务驱动方式,系统断定,系统安全如外挂做弊等相关问题,文章中再也不对他们进行对比说明。通常来说,根据游戏的规模与需求,一般游戏服务器的实现的模式会使用以下的三种架构方式来实现。

单进程服务架构

1 单进程服务架构

1是目前互联网上的不少游戏服务器使用的架构,好比商用的SmartFoxServer游戏服务器,开源的有Google Grits, Mozilla Browser Quest等框架。全部的程序在同一个进程里面运行,架构简单,开发人员上手快,开发和调试很是方便又快速,成本较低,后期的维护成本可能随着游戏项目的大小而不一样,可是总体应该不会过高。很明显,游戏的世界是在同一个进程里运行,在单个场景都有很多在线用户的时候,若是采用单进程的 Node.js 实现的话,每一个用户的操做可能会有必定的延迟,特别是在大量用户同时作大量操做与AI运算时,如服务端寻路和自动杀怪,延迟会更加严重;同时单进程对计算机资源使用有限。所以只适合游戏的原型制做或小型的游戏开发。另外,因为游戏的状态与复杂性,也没法较好的实现游戏的可扩展性,基本只能经过添加游戏服务器的方式来实现,即所谓的开新服,而这些用户之间是没法在同一个世界里通讯会话和交互的。尽管Node.js支持原生的TCP服务,使用简单;可是目前大部分网络应用中,尤为是支持HTML5的应用,socket.io因为性能较好而且使用简单,成为大部分应用采用的网络库来实现高性能websocket服务。在移动互联网应用中,因为协议较复杂与通讯数据等问题,须要必定的裁减。下面示例中,就是最简单的单进程服务的原型:

var socketio =
require('socket.io');
var io =
socketio.listen(8080);
io.sockets.on('connection',function(socket){
     socket.on('disconnect',function(){
     //user leave
     });
 socket.on('message',function(msg){
     if (getLoginStatus(socket)) {
    game[data.action].apply(null,[socket,msg]); 
     } else {
     game['login'].apply(null,[socket,msg]); 
     }
 });
});


多进程服务架构

2 多进程服务架构

在上图2中,咱们能够看出,每一个进程负责采用单一职责,各进程间经过必定的规则(如RPC远程过程调用)来进行通讯,游戏中的各场景服务使用一个进程来服务,实现各场景游戏运行的分离。可是在开发过程当中,不须要考虑每一个场景具体的信息,所有采用统一的代码来实现,开发方便,经过添加适当的参数来实现较易的调试,每一个进程分别运行在服务器的多核上,便可以充分使用计算机的资源,也因为职责单一,因为每一个进程都专职作本身的事,所以,在压力大的时候,能够很明显的查出问题所在,并能够较好的实现对相应的服务进行调优,能够达到较好的性能和必定的可伸缩性。可是,在各游戏的世界里,没法准确的知道游戏的状态如在线人数之类的,会存在热点数据和服务过载等一些问题,形成部分服务堵死等现象,也没法达到在不停服务的状况下进行服务器扩容与自动切换等问题,同时会给游戏运营带来必定的问题,不能充分的对玩家数据进行分析与挖掘,所以,这种实现方式能够知足中小型的游戏开发。这种架构目前不少的游戏服务器中还在使用,技术发展也较成熟,如传奇服务端架构等。

分布式服务架构

3 分布式的服务架构

一样,分布式的服务架构与多进程的架构具备不少相同点,如进程服务单一职责,较好的性能调优,同时采用集中式的方式对游戏服务器进行管理,各游戏服务器能够经过自定义的方式即DSL进行游戏业务的路由与分发,经过主备服务器的状态能够很清楚的知道每一个服务的状态及运行状况,这样可经过动态添加服务来到达负载均衡,具有较好的性能和可扩展性,能知足大型游戏的开发。固然,采用这样方式,会具备必定的复杂性,同时各服务之间多是不在同一台服务器上的,所以会带来必定的网络开销,在大量广播的场景中,网络IO压力大,须要经过定时批量或AOI服务等方式来进行广播通讯,同时,游戏的通讯协议须要通过特别的设计,尽可能避免数据序列化上的CPU重复开销,采用胖客户端的方式去分担游戏服务器的序列化与反序列化;另外还有可能引入分布式事务等相关问题,须要在一个集中点进行处理。固然,在游戏设计中,策划开发人员须要尽可能避免这种跨场景跨进程的游戏逻辑需求。

在分布式架构实现中,目前商业上较成功的案例是BigWorld游戏服务框架,国内外不少大型的游戏开发商都在使用。而在开源部分,目前尚未较稳定成熟的方案,咱们团队采用Node.js正在开发的Pomelo游戏服务框架正在努力实现这一目标,现已进入最后的文档整理阶段,预计将在十月份进行开源与线上示例演示。

总结

<span style="display: inline !important; float: none; background-color: transparent; color: rgb(51,

相关文章:
【推荐】 秋读|10本热门图书(人工智能、编程开发、架构、区块链等)免费送!

相关文章
相关标签/搜索