MMO游戏设计二:面向服务的设计

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lunar_lty/article/details/42081303

什么是面向服务的设计,其实自己也没整明白。总之,为了解决一下的几个问题。


1. 游戏服务器运行过程中,由于某个玩家的操作引起服务器CPU过高,导致其它玩家有非常明显的顿卡。

2. 某个模块引起的宕机,整个服务器需要停服维护。


解决的方法是,为每一个服务建立一个线程,每个玩家也对应于独立的线程,每个独立的服务之间通过消息进行通讯,而服务的内部接口则是直接的函数调用。举个简单例子,服务A有一个接口为CreatePerson,那么A线程使用A->CreatePerson时是直接的函数调用,而B调用A->CreatePerson时实际则通过发消息到A线程,A线程收到消息后再调用实际的函数进行处理。由于玩家对应于一个线程,所以即使某个线程挂掉或者非常耗时,也不会影响到其它玩家的服务线程。

上述逻辑实现起来很简单,CreatePerson调用的时候判断一下当前线程的上下文即可,然后再决定是调用函数还是发消息。但这样的实现方式很不优雅,代码冗余量大,暴露了一些底层实现的细节,我希望能找到一种通用简洁的实现方法。

首先想到的是定义一个通用函数(或者宏),由它来完成线程上下文的判断,决定直接函数调用或者是发送消息到目标线程处理。那么通用函数显然需要函数名(或函数指针)和实参表作为输入参数,函数类型的泛型化都好办(可以用模板),实参表也好弄,重载模板函数即可,比如重载带一个参数、二个参数、N个参数的模板函数。将函数调用信息(包括函数地址和实参)封装在一个消息里面,发送到指定线程处理,那么问题来了,由于无法知道函数类型,即便知道函数地址也无法调用函数,此外”将参数逐个解析出来“也无法做到泛型化。

另外想到的是函数调用hook技术,hook一个成员函数这个简单(有关hook函数可参考http://blog.csdn.net/ATField/article/details/1507122),但hook所有的成员函数这个就太繁琐了。


一个简化的设计是,和windows消息处理函数类似,设定一个具体的函数原型,所有调用函数都符合此原型,比如int (*CallBack)(int threadID, int msgID, void* data, size_t len);这样所有的Service接口都有一个这样的函数SendMessage,参数与此类似,任何Service类都从Service接口派生,另外Service接口还有一个纯虚函数OnMessage(),供各种不同的Service来Override。这样Service相关的逻辑都以消息的形式调用,比如A->SendMessage(0, MSG_CREATE_PERSON, data, len);唯一不方便的就是对参数进行封装和解析,这里和网络消息处理类似,需要进行序列化和反序列化。




猜你喜欢

转载自blog.csdn.net/Lunar_lty/article/details/42081303
今日推荐