多年前的一款页游《倾城》服务器源码分析


未完结版。业务逻辑代码 有点看不下去了,于是就放弃了。

1.网络层:


 

游戏代码中,网络服务器端 提供了两套实现,一套是SimpleNetServer,基于BIO(阻塞IO)的ServerSocket;另一套是NIONetServer,基于NIO(即非阻塞IO selector模式的ServerSocketChannel。前者应该是用于开发期间的调试和测试;而后者用于实际生产环境。

比较两者关闭服务器的方式,前者是直接中断线程的,比较粗暴;后者是通过设置轮训字段字段(running)的状态来关闭的,更优雅、可靠。

其他细节,详见代码。

心跳消息:NIONetServer.run() -> NetConnection.update()

 


 

NetConnectionclient连接,以及收发消息的操作做了封装。并有两个子类继承之,其中SimpleConnection对应于SimpleNetServer,是BIO服务器端的网络连接对象;NIOConnection对应于NIONetServer,是NIO服务器端的网络连接对象。

 

 

 

消息解码器/编码器:


 

Request消息NIO处理流程:


 

2.数据层

游戏把数据持久层和数据缓存层 合并为同一层了。所以这里就并为一层来一起讲解。


 

    如果非要分数据持久层和cache层,DataAccessor算是主要提供了cache的实现。持久层提供了2种实现:LocalFileAccessor是将用户数据存放在本地文件系统中,以文本文件的形式存在,详见localdata\*data\*,貌似data目录下的更齐全。目前源码中用到的是localdataDatabaseAccessor是将用户数据存放到数据库中,读了GameServer.init()中提供了mysqlmssql两种数据库可选,而配置文件config\server.cfg中配置的是mssql数据库的数据源信息,而且还提供了mssql的驱动包。

    DatabaseAccessor中,写数据库是异步的:创建一个包含jdbc sql语句和参数的job,放入队列中等待运行。对于插入操作,是先插入name,然后获取数据库生成的id,赋值到内存中,然后创建一个update job放入异步队列中等待更新。

    这一层的源代码没有太多可圈可点之处,问题却是比较多,比如sql语句硬编码到源代码中,jdbc代码充斥于各个角落,导致代码冗余且难以维护;数据持久层仅仅使用了单个队列、单个线程处理,在某些情况下风险很高,例如单个job处理时间过长导致后续job没有机会及时运行,尤其是当队列严重阻塞、断电或宕机时后果最为严重;不能充分利用多核cpu的资源。