游戏服务器扫盲

抽个时间,把java语言开发游戏服务器的技术盲点补上,方便复习。前端

注:这里仅仅是讨论流程解决方案,具体的细节等,不做说明。java

 

1.网络通信mysql

1.1 游戏客户端与游戏服务器的通信linux

客户端复杂多变,好比传统页游flash,手机游戏,h5等,所用消息协议不一样,但无非是tcp,http,websocket等。web

jdk传统的阻塞io模式,显然没法知足游戏高并发的需求。即便是nio(非阻塞io),对于研发人员来讲开发成本大,错误率高,对于之后游戏扩展算法

也是一个极大考验。sql

1.7之后,jdk提供了aio(windows上是经过iocp实现了真正的异步io)。这样全部的读、写、链接等通知,都经过数据库

事件来驱动。因为linux上未实现真正的异步,并且相比较nio,aio的效率提高不明显,目前这种方式使用很少。后面会单独一篇文章来讲明如何apache

使用aio。json

java语言的伟大之处,不只仅是在语言自己,各类各样的优秀框架也极大的简化开发复杂度。对于游戏通信这块,netty(目前4版本较多)必然是

首选。netty实在太优秀了,这里不做太多介绍,若是netty不了解的,能够看我前几篇博客的源码,或者买本关于netty的书籍。

 

1.2 客户端与服务器约定速成的通讯规则

通信框架咱们已经选用netty了,咱们已经接受到了客户端的链接,网络传输的码流如何解析成程序熟悉的pojo对象,如何避免粘包,半包,

接着如何处理客户端发送的消息,服务器又是如何通知客户端呢?

  • 与客户端约定完整的一套,好比长度size(int),msgId(short),content(xxx),自定义解析协议
  • protobuf
  • 特殊分隔符等等

经过上面几种方案,能够简单的解决粘包和半包问题,netty经过某种神奇的手段(哒哒。。。)终于拿到了客户端发送的消息内容。

这里netty处理的内容不少,好比channelHandler的链式流程,好比ssl认证,读写超时,tcp最大链接数设置等,我就不细说了。

 

2.复杂的线程模型

游戏的线程模型,较为复杂,画图比较容易理解。这里我就偷懒,概述一下常见的解决方案。

2.1咱们知道,在1网络通信里所说的一切消息编解码,转换pojo对象等,都是io作的事。io的线程数量,也是伴随着游戏类型和复杂度

不一样而不一样,咱们一般的设置是:cpu+1。

2.2上文中,咱们经过某种神奇的手段,拿到了客户端发送的消息内容,这里依然是io线程,你能够想象下,若是客户端发送一个A消息,

让咱们从数据库load 10W条数据,这里会有必定的延迟操做,然而对于密集型的任务若是存在延迟,那么玩家登录、发送消息等会存在卡顿,

这对于rpg的游戏来讲,简直就是灾难。

2.3既然有卡顿了,那简单啦,加个业务线程池,这个线程池的数量一般是:cpu。业务线程池执行咱们业务代码逻辑,客户端发送A消息,

咱们把A消息封装成task,放在线程池里最终执行。

好像能够了?

咱们如今假设,客户端先发了A消息,再发B消息,按照tcp和netty的处理机制,转到游戏这边应该是A-->B的过程。可是咱们抛到线程池了,

如何保证线程池执行的有序性?阻塞队列吗?他们都不在一个thread里。

2.4如何处理玩家消息的有序性?

客户端与服务器的连接,至关于一个对话,有对话就必定有channel,有channel有必定有session(我封装的xxSession来管理channel)。

针对同一个玩家用户,session不变,session管理的channel不变,那么channelId就不变。

每次客户端不论是发送A消息,仍是发送B消息,他们的channelId都不变。因此在抛到线程池执行前,作个简单的hash算法,保证

相同的channel都在同一个线程里处理。

2.5还有吗?

好比工会、氏族、抢购等业务,设计到公共数据的地方,玩家必然会有交互,如何保证数据最终的一致性呢?

有的朋友说加锁,对,锁是处理这种交互数据最简单,也是最暴力的一种方式。这里我引入了actor模型,我经过对比发现actor的模型

不是通常的好,他不只能够共用线程池,同时还能让全部的任务分片执行,不至于让某个线程一直忙于处理某个集中型的任务。

若是对于actor不熟悉的同窗,能够借鉴akka actor,我这里用的是java actor。具体不细说。

2.6没错,上面的流程只是适用于slg,棋牌类型的游戏,若是是针对rpg的场景类型呢?

解决方案就是加上玩家在场景的场景拷贝,以前2.4以玩家的channelId 进行hash索引,这里以场景的sceneId为单位便可。

 

3.跨服、多服的简单解决方案

上面2步实现了单机最简单的消息投递方式,新的问题又来了,若是把网关服,用户服独立开,场景服务器独立开,跨服等如何实现呢?

java多进程之间通信,看来rpc要派上用场了。游戏这里不比电商等业务,咱们全部的服务都是同java语言开发维护,因此一个简单的chen-rpc就能够搞定啦。

rpc具体的实现细节,不做过多讨论。咱们实现的最终目标,远程调用,就像本地调用同样的方便便可。

 

4.游戏后台管理系统

简单的前端框架xx抄过来,连ui都不用啦。

http服务,本身写了一个,tomcat都省了,gm指令,web后台登陆权限控制,运营客服线上操做等,恩,不用太复杂。

固然,运营让你复杂,仍是要搞一搞的。

 

5.游戏静态数据的配置维护

策划常常更改静态表数据,对服务器来讲,这种常驻内存的数据,

若是更改一次,服务器重启一次,这样不只仅是内网测试困难,线上怎么办呢?

5.1首先,策划表数据配置通常都在excel中,这里须要提供一个Excel解析工具,将excel数据,转换成data.dat配置,或者json等,最终生成在服务器项目下的resource

资源包下。

5.2策划更新维护时,经过4的游戏后台,上传data.dat文件,同时从新reload静态资源数据,将java内存值更改 。

 

6.动态数据的更新维护fixme

有静态数据,那必然有要动态更改的数据,这种数据如何落地?会有缓存穿透吗?若是线上有段代码须要更新,怎么办?

6.1目前我接触的几款游戏项目,选用的数据库都是mysql,同时游戏服务器内部有缓存。具体的缓存同步到数据库方式,通常有两种:

  • 阻塞的队列,队列中有数据,就往数据库更新
  • 定时消费,同步数据库

好了,orm开始登场啦。游戏的数据类型简单,表设定更容易,须要事务吗?应该是不须要的。

因此,除了那些大的框架,好比hibernae,jpa,ibatis等,咱们能够本身写一个简单的orm,具体参考:apache下的dbUtils

6.2java的一系列因素,决定了动态更新必定不是件容易的事。目前动态更新有多种,具体不做详细介绍。可是,原理无外乎两种:

  • 重写classLoader
  • 关于Agent Main 

 

7.寻路、视野

3d和2d目前我接触的两款游戏设定不同,具体的我单独分篇来介绍,这里不过多说明。

 

8.游戏压测

这个我比较擅长了,目前也是主要干这个事情,具体参考我上篇关于机器人压测的介绍。

 

9.游戏日志系统

日志系统很重要,不论是运营正常的数据需求,仍是咱们程序线上查找问题,日志都是比较完美的解决方案。

具体也不细说了。

 

10.战斗系统+棋牌算法

10.1 slg回合制战斗

10.2 rpg即时性战斗

10.3 斗地主等

单独的文章来讲明,具体不介绍了,每一个玩法也不尽相同。

相关文章
相关标签/搜索