要想设计好网络游戏服务器的构架,首先需要知道网络游戏服务器在玩家游戏过程中发挥什么作用。就我个人的理解:网游服务器在玩家游戏过程中扮演上帝的角色。玩家在服务器制定的规则下进行游戏,服务器负责同步在线玩家之间的属性、操作、状态等等,最终在多个不同的客户端呈现一个“统一”的游戏世界。 所谓的服务器构架在本系列blog中,主要是指如何将服务器各部分合理的安排,以实现最初的功能需求。好的结构不是一蹴而就的,是通过需求的推动一步步的完善。而且每个设计者心中的标准不尽相同,所以我认为并没有绝对优秀服务器构架。本系列文章中所谓的优秀构架是指各方面达到一种平衡(包括成本等的非技术因素)。 下面先介绍刀剑Online的服务器构架(后续还可能有WOW、天龙等): 图1 刀剑Online服务器构架 看了像素的技术总监魏华的文章[1],感觉有点意思。文章中所介绍的服务器构架并不复杂,但满足一般MMORPG网游要求应该是绰绰有余了。按照魏华自己的话,这样的服务器构架主要满足能够接受以下几条**的网络游戏:
服务器包括游戏中和游戏外两大部分,这里主要讨论游戏中的服务器构架,类似客户端自动更新等的游戏外服务器不在本文的讨论范围。 接下来对刀剑Online的服务器构架的各个部分进行详细的分析,其中包含很多我自己的想法,很多内容都是我猜测的,因此不能“信以为真”。 游戏客户端在游戏过程中实际上是和连接负载服务器(简称CLS)进行连接并做数据交互的。如文中[1]所诉,CLS主要的作用是:
图2
连接服务器的主要工作正如上述魏华谈到的,但有几点并没有做出强调,下面本人结合平时的实际工作给出一些补充(不一定正确): 根据经验: CLS作为与client建立连接、进行数据交互的“Gate”,从程序角度来看CLS的代码应该是最简洁高效的。因为CLS主要负责与客户端交互数据是的加密解密、以及数据搬运。而使用流加密算法RC4对整个数据流进行加密解密是很耗CPU的,因此代码的高效在这个模块是十分的重要。 为了提高程序的运行效率,CLS程序往往会使用-O3的选项进行编译,这无形中又对代码的编写有更高的要求。CLS一般会有自己的打包机制(控制发送频率),因此常会使用TCP_NODELAY选项禁用Nagle算法。 CLS常会被分配到不同的物理机器上,因为操作系统在处理TCP包时,需要通过软中断来通知进程或者唤醒system call,在服务器十分繁忙的时候CPU可能处理不过来。解决办法是:使用多核的服务器,然后把TCP的软中断平均分配到多个CPU。(一些操作系统默认只使用0号CPU来处理,Fedora Core release 2默认就是只使用0号CPU,较新的版本我没有做研究) CLS在做数据流的解密后,往往需要把数据包构造成内部服务器进程间通讯使用的protocol,这种protocol模块要独立,序列化和反序列化的接口要稳定,这样以后需要更换协议模块也不至于伤筋动骨。可以使用像google的protobuf这样的开源协议,减少开发难度。 CLS负责建立和client的连接,多会使用多个CLS进程才能支撑1w的在线人数,因此在CLS前端一般会有负载均衡的程序,负责把建立连接的请求均匀的提交到各个CLS。 有一个需要讨论的问题:作为服务器端的“Gate”,只负责数据转发的CLS是否需要对client发过来的数据进行完全的解密?或者只解密包头,知道转发的目的地即可?(RC4并没有增加流的长度,因此可以只做部分解密) CLS只做部分解密: 好处:将耗费CPU资源的解密功能分摊到别的进程;各进程各服务可以在解密后用不同的方案来构造自己的protocol。 CLS做完全解密: 好处:可以提前过滤部分无效的消息,只做部分解密也可以做提前过滤,但是这样太过于依赖协议的设计;在CLS处做完全解密,则往后服务器端的之间的消息传递都是明文,利于抓包查错;由于CLS的功能比较简单,很容易通过加机器来进行扩展,因此计算放在CLS上是比较明智的选择。 CLS是一个功能相对简单但要求代码简洁高效的程序,在设计实现的时应该注重效率及代码编写规范。经过对比在CLS程序对数据流进行完全解密是利大于弊的,推荐使用这种方案。 感谢阅读本文转载于微信公众号: 泰斗(mptaidous),更多微信文章请扫描关注公众号: |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|