大家好。
我是一个热爱技术的人,从事商业的服务器开发9年多,参与和负责了几款不同类型的游戏开发,包括SNS、ACG和RPG;也负责过IM的开发。运气比较好,属于实战型的程序员。我想写一个游戏服务器的序列文章,主要是自己实践的总结。发帖目的是想大家给点意见,怎么写,对须要经验分享的人有效果。我将在业余时间慢慢写,慢慢地写,争取每一部分都对读者有益。
首先说一下我的写作原则:
1 实践干货
从实践出发,没实践过的,尽量不写。如果一些平时技术学习类的内容,会单独作为章节列出。人非圣贤,必有错,实践的内容不合理,大家指出,表示感谢的同时立马改正。
2 简单平实
介绍的内容不玩虚,能用简单方法实现,绝不用奇淫怪巧的技术,把事情搞复杂化,以显示自己的技术水平。很多地方用到多线程,但实际是无互斥、无同步,写逻辑和单线程的无差别。对于性能优化也适可而止,防止代码复杂化,出Bug。
3 不发明轮子
没有特殊的需求,只用通用API,主要是标准C++库和特定平台的Socket、线程API等。那种重写STL什么绝对不干。
4 内容收敛
就专注写游戏服务器的技术,对一些基础技术,比如面向对象、C++模板、网络基础的API和TCP/IP基础知识之类的不涉及。
写作目标
游戏服务器的新手可以在阅读系列文章之后,可以从事商业项目开发,将序列文章作为参考知道自己该怎么做。而有经验的呢,也可能或可以从文章中得到不一样的实现方法,提升一定的技能。
写作大纲
前言
简单介绍序列文章的组织结构,不同的读者查阅方法等,软件平台约定之类的。这章没什么好说。
1 游戏服务器架构
由简入全的方法介绍分别对应不同的游戏类型服务器架构,不同类型和不同分区方式的服务器架构基本大同小异,我尽量整理出共同点,然后附加说明SNS类游戏需求比较奇葩架构方面处理方法。游戏服务器架构我个人倾向于分接入、逻辑和存储三个层次去实现,实际内容也按这三个层次展开。
2 网络通信
设计理念
讲述性能与实现复杂度的取舍。
多线程使用之道,这个不是直接介绍如何使用线程、处理线程间的数据同步,这些技术相信大家都很容易掌握。文章将着重讲述多线程无互斥(Lock-Free)实现的方
法,逻辑层与通信层线程上下文的关系。最终我们得到的结果是,用了多线程,但无须互斥(加锁),最大发挥多核的威力;写大量的逻辑层代码的时候,和写单线程代码
一样,简化逻辑,使系统稳定。
通信功能
还是有必要花时间介绍select(Windows客户端有时候要用)和epoll。
缓存队列-无锁Buffer
缓存队列-减少数据拷贝
逻辑层服务器抽象对象
这块是逻辑层和通信层的桥梁,这里涉及到多线程的无互斥的细节。看过公司的几个项目,发现这一块其实做得不理想,存在CPU的浪费。所以我的方法应该还有一定
的参考价值。
TCP流和应用层的消息
简述TCP流, 提供一个简单的TCP流转化为应用层的消息的策略;简述常见的几种消息Encoding&Decoding的策略,简单地分析取舍。这里将提到我们项目里用到的
第三库,protobuf;还会提供一种基于二进制Encoding&Decoding的实现。
3 基础设施服务器
这些服务器完全通用,不同的项目基本上可以直接使用。
通行证服务器
有的公司做的服务器都是每个项目都有各自用户名密码验证模块。这里将介绍用Kerberos实现的通行证服务器。
更新服务器
服务器列表服务器
接入服务器
讲述为什么要用接入服务器,如何实现。
4 游戏逻辑-概述和架构设计
这部分涉及内容蛮多的,我打算先说清楚逻辑服务器的架构设计,然后分别简述游戏中都用到的模块。基本上不同类型的游戏都差不多。我设计和实现模块原则就是尽量低耦合,不同模块将非常独立。
逻辑服务器架构设计。
关于脚本
5 游戏逻辑-基础设施
C++与Lua交互
数据处理模块
基础逻辑模块
这个主要是一个事件分发的功能,各个逻辑模块相互联系互动的纽带。另外就是游戏对象基础设施。还有基于多线程(还是Lock-Free)的日志系统。
简单的异步处理机制
写逻辑的时候,我们看不到各种请求处理是异步的,和写同步阻塞代码一样。这个值得大家参考。
6 游戏逻辑-功能模块
开放式空间模块
游戏大世界,大家都可以随便进入的空间。
封闭式空间模块
房间、副本、战场之类的。
角色基础模块
宠物基础模块
单位属性模块
单位动态属性模块
这个上面有区别,动态属性是什么呢? 像角色或者宠物参与战斗或者什么活动,这些属性会变化的,都称为动态属性。
视野控制模块
背包模块
经常说道具背包,我们要把背包独立出来,做到和道具完全无关。
道具模块
道具可以放在任何地方,常见的就是背包里,也可以在邮件附件中。
任务模块
成就模块
小游戏的成就比较少,可以用和任务一样的代码,成就的行为和自动接受的任务是一样的。但复杂的游戏,成就有很多,几百上千的,这时候可以参考这里的实现方式。用了优化策略,系统性能损耗基本上和成就个数无关了。
战斗模块
如果是不分区的服务器,这个将会在独立的进程中跑起来。做成分布式。这块将提到一个有趣的系统当机后重启,原先玩家所在的PVP战场有效性的处理机制。
队伍模块
聊天模块
Buff模块
游戏中,到处都是Buff对象。
技能模块
回合制的和即时的有差别,回合制的比较简单。即时的,像RPG类的技能,实现的时候有一些小讲究,不能实现的太直
接,否则吃CPU有时候比较多一点,要让客户端配合做一点事情。
AI模块
天赋、种族专精类模块
这个专门针对那种你有多少什么点,可以加什么属性值之类的,表现上看起来细节很多,乱七八槽的。在实际项目
中,我用了一点小聪明,代码实现非常简单。要实现什么功能全由策划配数据。如果,比较实诚地去做的话,搞不好就偏复杂,容易出Bug,容易被作弊。
7 游戏逻辑-进程级的功能模块
这些模块功能比较完整,一个模块对应实现成一个的独立进程。从表面看,进程太多了,提高运维的复杂度。实际上还好,这些进程配置都简单,而且对外提供独立的功能,即使当掉了,也不影响整体游戏体验,最多表现在玩家没法用某个功能了。
好友模块
公会模块
公会模块独立地在一个进程里,如果公会会影响另外一个进程中的战斗Buff,影响玩家的人气值的获取,怎么办?强制交互是下下策,会让我们代码变复杂,不易维
护。这里将会给出比较合理的参考。下面联盟之类也类似。
联盟、血盟模块
邮件模块
商城模块
动态模块
这个基本上借助后面讲到的存储代理实现掉。
8 Cache和存储
存储包括存储前端的Cache和后端的数据落地。我们将简述一个通用的存储代理,然后把数据写到MySQL。MySQL只做为数据落地的工具,不做其他用途。这一章将涉及LRU什么的;一些分布式的常识,比如简单Hash映射、一致性Hash;同时借助反射的机制实现通用的数据Cache和存储系统。
概述和架构设计
实现
附录
1 大世界游戏服务器
有一段时间业余的兴趣爱好,当时也只是实现了简单的demo,没有机会在实际项目中应用过。这个讨论大地图的一种比较简单实现方法,涉及到前面章节的多线程的无互
斥的技术。讨论的服务器不是可以无限大,是基于单台服务器如果核数足够多的话,如何充分利用多核,支持更多的玩家逻辑处理。某个角色可能跑到任何的线程中,编程的时候,就全部采用异步的方式,即时交互的双方是在同一个线程中。
大纲写完了。有兴趣的同学们请提意见,谢谢。
email:
[email protected]