棋牌高防服务器架构q8803582
首先要说明的是, 这个棋牌游戏的服务器架构参考了网狐棋牌的架构。网狐棋牌最令人印象深刻的是其稳定性和高网络负载。它的一份压力测试报告上指出:一台双核r的INTEL Xeon 2.8CPU加上2G内存和使用共享100M光纤的机子能够支持5000人同时在线游戏。
在研究其服务器框架后发现,它的网络部分确实是比较优化的。它主要采用了Windows提供的IO完成端口来实现其网络组件。本服务器虽然参考了其设计,但是还是有很大的不同,因为这个服务器框架主要是用在linux系统之上,而网狐棋牌是基于Windows平台的,严重依赖于windows sdk。这个架构延续了网狐棋牌在网络组件所作的努力,这个棋牌的服务器也使用异步IO作为网络的工作方式,更为彻底的是其数据库也是采用异步架构。boost::asio提供了一个异步框架,所以它的几个核心组件: TCPServerService, TimerService, DatabaseService, AsyncService中都可以看到boost::asio的影子。
, 图1是总体架构图。从图上我们看到服务器的整体架构分为三层:Libraries, Core和Applications。Core层基于Libraries实现,而Applications使用Core层提供的服务,并且要监听Core层的异步事件(Socket、Database等)。
图1 棋牌游戏服务器端总架构
Libraries 主要由4个库组成,其中boost::thread是一个跨平台的线程库,boost::asio是跨平台的异步IO库,protobuf则是用来序列化服务器和客户端协议的, libpq是开源数据库postgresql提供的客户端的官方接口,支持异步数据库操作。
Core 主要由4个Service组成,它们建立在Libraries的基础之上。给应用层提供了网络,数据库和定时器功能。AsyncService主要是Core内部自己使用。TimerService提供定时器功能,TCPServerServic管理着客户端来的连接。而DatabaseService提供基本的数据库访问功能。
Applications是基于Core实现的4种服务器,它们管理着游戏信息,提供登录以及处理游戏逻辑的功能。下面是用户与这些服务器交互的一个经典流程:
1) 客户端将用户名和密码发送给LogonServer登录,在登录验证成功以后,将游戏列表返回给客户端。
2) 玩家选择具体游戏进入房间时,客户端发送请求给RoomServer,RoomServer将房间的信息返回给客户端显示
3) 玩家选择桌子坐下,游戏开始。客户端将游戏动作发送给相应的RoomServer, RoomServer将操作解析后转发给游戏逻辑模块进行处理,并将处理结果返回给客户端。
这几个服务器这间的关系是:
1) CenterServer维护游戏列表信息和房间信息;
2) LogonServer定时从CenterServer取回游戏列表信息和房间信息;
3) RoomServer在启动时向CenterServer注册,在关闭时从CenterServer注销, 以玩家进入房间时通知CenterServer更新在线人数。同时像LogonServer一样定时连接CenterServer更新游戏列表和房间信息。
1 Libraries层
boost::asio是一个异步IO库,提供了一个通用的异步框架,并提供了基本的socket的异步接口,它的主要功能是响应程序的异步IO请求,在操作完成以后,将其加入到一个完成队列之中, 在这个完成队列上有一些工作线程在等着,这些工作线程从完成队列上取出已经完成的操作,调用上层应用提供的一个完成函数--completaion handler。asio库是通过学实现Proactor模式来完成这些工作的,在Windows是直接基于I/O completion port,而在类Unix系统中,是基于epool等函数使用Reactor模式来模拟的。
libpq是开源数据库postgresql提供的客户端接口库。这里选用postgresql是因为postgresql的跨平台性以及其稳定性和高性能,另一方面是由于我对这个数据库比较地熟悉。Libpq也对数据库的连接、查询、更新等提供了异步实现。可以和boost::asio结合在一起提供统一地异步操作接口。
boost::thread库是用C++实现的一个跨平台的线程库, 在C++11中,它已经被纳入到了标准库中。这个库在这里主要用来实现一个线程池,作为boost::asio的工作线程。主要是由Core层的AsyncService来维护。代码的其他地方不直接启动线程。但是在异步操作的完成函数中,对那些共享数据需要加锁保护。
protobuf库是Google发布的一个开源的用来序列化对象的高性能的库,它支持多种语言,比如C++,Java,flash 等等。同时还将字节序等琐碎的东西封装起来了,方便上层应用。
2 Core层
核心层由4个Service: AsyncService、TCPServerService、TimerService、DatabaseService组成。下面是关于它们的基本描述.
AttemptService是Core内部使用的,它封装了boost::asio和ThreadPool的功能,提供给其他几个Service使用。从名字上可以看出,他的主要功能是给其他几个Service提供异步调度,这是通过boost::asio提供的功能来实现的,而ThreadPool是提供给boost::asio作为工作线程的。
TCPServerService有一个连接池,管理着客户端来的连接。内部通过AsyncService将socket读写完成消息,通过应用层注册进来的TCPServiceObserver通知到调到应用层去。它和Applications的交互包括:
1) Applications 调用 SetObserver注册用来接收网络读写完成消息;
2) Applications 调用 SendData 发送数据;
3) Core在accept, recv完成后调用 Applications注册的Observer。
TimerService提供了定时器的功能,Applications层可以直接使用它来创建定时器,取消定时器。设定时间到来时,TimerService会调用创建定时器时指定的一个回调函数。
DatabaseService封装了libpq,提供数据库的基本操作。主要管理数据库连接,执行查询操作,执行存储过程等。它的实现中有一个连接池。和socket操作一样,它提供的数据库操作都是异步执行的,所以Applications层需要实现DBServiceObserver来监听操作结果。
3 Applications
前面的无论是libraries还是core,都是死的,只有applications加入了逻辑,它们是棋牌服务器的主休。下面是关于它们的比较详细的信息
3.1 CenterServer
图2 CenterServer与外界的交互图
CenterServer不直接与玩家进行交互,它主要的功能是管理游戏列表和房间信息,包括:
1. 游戏类型信息: 棋牌游戏、休闲游戏、视频游戏等。
2. 游戏种类: 比如在棋牌游戏这个大类之下有:德州扑克、斗地主、升级等。
3. 站点信息: 因为这个服务器架构完全支持分布式,所以还保存有站点的信息
4. 房间信息: 维护当前有哪些房间以及房间当前的在线人数。
CenterServer中有关游戏列表的信息是它在启动的时候从ServerInfoDB这个数据库加载的, 而它的房间信息来自RoomServer,RoomServer在启动时将自己注册进来,在关闭的时候从CenterServer中注销自己。同时在玩家进入房间的时候,还会要求CenterServer更新在线人数。