node-php-server 游戏服务器框架
2022-12-07 14:06:10 【

做游戏服务器多年,用过lua, 用过C++, 用过nodejs ,最近用的是php,有些人会说php不是用在web开发吗,怎么能用在游戏服务器的业务逻辑开发,php 怎么跟客户端通信,肯定有很多人不解。


其实很多时候,技术原理都是都是相通的,php能用作web开发,浏览器通过http协议发送数据给nginx ,nginx 再转发数据给php-fpm,之后php-fpm 再执行对应的php脚本,得到脚本执行结果,返还给nginx,再通过nginx 下发给浏览器显示网页效果,这中间的过程是短连接的过程,而游戏服务器大部分是长连接,所以把nginx 改造,或者参照nginx 原理,重新做一个网关服务器,维持长连接,进行多进程的负载均衡,让每一个耗时的操作,尽量不要影响到其也玩家,所以自己抽空弄了一个小型的游戏服务器框架,就是node-php-server。


php-fpm 怎么执行php 脚本不用太去关心,这已经是很成熟的模式,只要是用php开发的web相关的,大部分是php-fpm这一套。重点是使用cgi协议与php-fpm 通信,多进程的管理,怎么负载优化,进程的监控等.


node-php-server 其于nodejs 开发的多进程游戏网关服务器,每个玩家的连接进来,都会分配到不同的业务进程进行逻辑处理,每个进程之间互不干扰,即使有个别进程因各种原因处理慢,其他进程没有任何影响,因此对玩家体验也比较好,不会因为有个别的长耗时命令,导致其他玩家的操作得不到及时的处理,影响游戏体验。


每个连接绑定在固定的进程,后续的消息,都在该进程处理,保持玩家操作的时序性,这个在游戏服务器开发中很重要,因为服务器同时处理了同一个玩家的多条命令,会导致意想不到的数据混乱,比如得到了两个道具,却只花了一次的钱,这些都是在游戏开发中的大忌。node-php-server严格按照时序性的原则,每个进程都有对应的消息对列,上一条命令处理好了,才能处理下一条,这样可能效率偏低,但是逻辑严谨,后面可以做优化的,比如把同一个玩家的命令,集中处理,减少中间的传输时间。


node-php-server 也有相应的进程监控,有业力进程退出时,自动补充一个新的进程,之前绑定在退出进程上的玩家连接,可以无逢切换到新补充的进程,对玩家没有任何影响。


对于游戏的推送,广播,可以由php脚本发起连接到node-php-server,再由node-php-server 转发消息给相应的连接,来达到推送的效果,但是没法做到把转发的过程放在子进程之中,因为还没找到相应的方法,把对应的连接正确地由父进程传到子进程,所以只能把转发的过程还是放在主进程,如果转发的过程有卡顿或者意外,都会影响node-php-server的稳定,这也是使用过程中需要注意的地方,也是后面需要优化的地方。


php层写逻辑,有很多的方便之处,不用关注内存的处理,有错误也不会影响游戏服务器的稳定,开发效率快,扩展多,说实话,再大的游戏的也不用996。


使用的时候直接修改 config 里面的配置文件就可以,再就是修改php-worker.js 里面php脚本的路径就可以,用php脚本写业务是真心方便。



最近又优化了一个版本,可以看下gitHub 的提交记录


因为在测试过程中发现,一个工作子进程处理多个连接的请求时,有个别请求,耗时过长,结果其他后来的请求,都得排队,导致后面的请求耗时,无形就拉长了,这个在游戏中,对玩家体验肯定很不好,所以就想办法怎么样减少排队,把一个连接的请求,均匀地分配到每个子进程,这个也不是很好,逻辑有点混乱,没法保证单个玩家的游戏逻辑顺序处理,有并发的情况,另外也一样面临着排队的情况,所以必须给服务器的处理能力扩容。


扩容有两种方式,第一种增加工作子进程,但每个工作子进程,所占内存就有20多M,加多了物理服务器吃不消,成本太高。所以只能增加子进程的吞吐量,提高子进程的处理能力,所以对工作子进程进行了优化,这里得用到nodejs 异步回调的特性,主进程收到客户端连接的逻辑请求时,在工作子进程的排队范围内,只管向子进程发送消息,子进程收到消息之后异步回调执行逻辑请求,也就是与php-fpm 进行交互,得到处理结果。这样就是在子进程就可以同时并发多个与php-fpm的请求,服务器的处理能力就可以几倍几倍的增长,达到扩容的要求,而不用增加消耗过多的物理内存。



工作子进程会准备多个php-connect,有消息过来时,会找到空闲的php-connect去与php-fpm进行交互,得到返回结果,再通知到主进程。因为每个子进程的php-connect 是有限的,主进程向子进程投递消息的数量,不能超出子进程php-connect的数量上限,否则会造成数据请求丢失,这个代码里面已经做了相应的处理。后面可以通过调整配置文件,来调整服务器的处理容量上限。


{

   "server_ip": "10.0.0.1",

   "server_port": 4439,

   "php_fpm_ip": "10.0.0.1",

"php_fpm_port": 9000,

"php_connect_num":10,

"worker_num":36

}

worker_num 工作子进程的数量,php_connect_num 工作子进程php-connect 数量


上图这里的配置 保证同一时刻,可以并行处理 360条逻辑请求,哪怕有一条或者多条请求耗时60s,其他的请求耗时,都不受影响。写了go脚本测试,并行800玩家测试,随机间隔几秒发送请求,没有一个请求在排队,耗时都很均衡,不会出现有的耗时长,有的耗时短的情况。


当然这种优化也有不足的地方,那就是会存在,一个玩家的多条网络请求,并行处理的情况,会造成逻辑混乱,这个也有解决方案,可以在php层控制,比如加锁,保证业务逻辑正确,也可以在主进程消息分发时进行处理。其他对游戏开发来讲,有并行处理也很正常,客户端有些是同步发送的,比如点击某个按钮,肯定是在等返回,才能做其他操作,也有异步发送的,比如后台心跳,这些是客户端主动请求,玩家不用感知,这些就避免不了并行处理,所以只能在逻辑层加锁控制,正常情况下逻辑并行处理的情况比较少,因为玩家做了一个操作,必须等到服务器的回应,才能做下一个操作,出现逻辑并行处理的情况,可能是遇到了外挂,钩某个接口,后台向服务器请求。


】【打印关闭】 【返回顶部
上一篇没有了 下一篇Python真的不适合游戏开发吗?游..