抽个时间,把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对象,如何避免粘包,半包,
接着如何处理客户端发送的消息,服务器又是如何通知客户端呢?
经过上面几种方案,能够简单的解决粘包和半包问题,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的一系列因素,决定了动态更新必定不是件容易的事。目前动态更新有多种,具体不做详细介绍。可是,原理无外乎两种:
7.寻路、视野
3d和2d目前我接触的两款游戏设定不同,具体的我单独分篇来介绍,这里不过多说明。
8.游戏压测
这个我比较擅长了,目前也是主要干这个事情,具体参考我上篇关于机器人压测的介绍。
9.游戏日志系统
日志系统很重要,不论是运营正常的数据需求,仍是咱们程序线上查找问题,日志都是比较完美的解决方案。
具体也不细说了。
10.战斗系统+棋牌算法
10.1 slg回合制战斗
10.2 rpg即时性战斗
10.3 斗地主等
单独的文章来讲明,具体不介绍了,每一个玩法也不尽相同。