基于多线程的大容量MMORPG主逻辑服务器实现策略

转载请标明出处:http://blog.csdn.net/herm_lib/article/details/9079309

实际参与的商业项目而且已运营的服务器,逻辑这块都是一个独立的单线程的,网络跑在其他线程中。像接入服务器,由于他自身的特点,可以尽量利用CPU,做到大负载接入。大部分商业服务器,包括网游服务器,瓶颈还是在于逻辑而非网络,所以接入服务器这块也没有必要的优化。

以前总结过接入服务器的优化的策略:游戏网关服务器性能优化的一种方案http://blog.csdn.net/herm_lib/article/details/7085181

今天想到了大世界服务器,以前出于兴趣,基于多线程实现了一个逻辑服务器,当时印象比较深刻。但随着时间的推移和年纪增长记忆力衰退,发现当时实现策略已经不再清晰。重新翻了一下以前的代码,好好地回忆,赶快把自己的理解记录下来。

今天的话题说得直白点就是,类似WOW这样的游戏,如何能做到支持最大数量的同时在线呢?这类游戏大地图是一个公共的开放空间,而且玩家角色之间是相互可见的,须要控制视野。实现大型战场的话,可以考虑参考本文的方法。

今天的文章基于的前提条件

服务器硬件足够强大,4CPU8核或者8CPU16核之类的。单台机器如果不够强,采用网络分布式的方案,理论上是不满足高即时的逻辑要求的。

要支持最大数量的同时在线,本质上就采用分布式策略。

一种方法是将地图分成多块,分配特定的线程为某块服务器。这个策略基本是不可行的,因为每一块的地图角色数量是不均衡的。除非,从设计角度强制每一块地图的人数有上限,这样就回到那种常见的小地图,跑两步就要传送到另外一个地图块模式中去了。

我这边采用的方法是,将不同的玩家角色分配给不同的线程,比如有角色R1 R2 R3, 线程 T1 T2 T3, T1跑R1逻辑,T2跑R2逻辑。。。。 线程分配方式,可以简单地为R1算个hash值,然后对应到哪个线程上。

这种方式在技术实现上,存在两个稍微麻烦一点的地方:

1. 线程互斥

2. 不同线程中的角色数据交互

第一种就是一种纯技术实现方案,我们要做到的是,多线程,但无须互斥。如果多线程,还要用各种锁,基本上玩家一多,线程一多,再多的CPU最后可能沦落到和一个CPU接近的负载。现在这个问题就归结到如何实现多线程不加锁了,基本上通过下面两点搞定:

[1] 一生产者线程一消费者线程,通过Memroy Barrie可以不用加锁,Memory Barrier,大家搜索吧。

[2] 多生产者多消费者,可以转换成[1]中的情形。

接下来说说第二个问题,角色间的数据交互,交互形式有两种,一种是线程内的,另外一个是线程间的。同一个线程内的两个或者多个角色数据交互,基本上是直接同步调用就行了。 线程间的有讲究,发展成类似服务器间的数据交互,从实现角度讲,可以认为和服务器间的数据交互是一样的,要做成异步的了。

就拿线程T1中的R1要获取T2中的R2的等级等信息,来说事,一般我们是获取角色基本信息,细节步骤如下:

[1] T1写 R1获取R2基本角色信息的请求消息(记为GET_ROLE_BASE_INFO_REQ),到 T2的线程队列;(R1就去做其他事情了啊。。。)

[2] T2取到 GET_ROLE_BASE_INFO_REQ,将 R2的 基本信息的回应消息(GET_ROLE_BASE_INFO_RES),写到T1的线程队列;

[3] T1读到T2的回应消息,通知给R1。

过程没有什么特别,和我们客户端和服务器,或者服务器之间的数据交互完全一样。 为了做到线程内和线程间的统一,线程内的角色间数据交互可以和线程间的方式统一起来。

上面的实现策略,在目前硬件条件下是可行的。有兴趣的兄弟可以实践一下,真正实践起来就有感觉了。