游戏服务器 断线重连机制原理

游戏服务器中所谓的“断线重连”,其实主要有几种情况: 1. 玩家断线,再重连服务器,中间时间相对较长(比如20秒以上)。 2. 玩家断线,再重连服务器,中间间隔时间很短(比如3秒之内)。

第一种实现上很简单,就是下线存盘上线读盘而已。可能唯一的区别是存的数据多少的问题,有时候要玩家处于不同的状态而存不同的数据。

举例:玩家处于一个关卡\副本\对战中,这个时候断线重连,和玩家处于主城中短线重连需要存盘的数据就不一样。如果玩家重连后关卡\副本\对战并没有结束,一般我们希望能让玩家继续处于关卡\副本\对战中,而不是已经退出关卡。最直观例子就是炉石传说的断线重连,玩过的都知道,比如我和对手在打,打到1费回合我掉线了1min,然后我连上来发现已经到3费回合了,中间的2费回合由于我掉线我什么都没做,空过了,但是我连上来的时候我还是处于对战中的,而且状态是对的,3费回合。简单说就是一句话:任何时候玩家掉线服务器都保存了玩家的所有状态,并且在玩家上线时正确恢复这些状态。

这种感觉实现起来也不是很麻烦,比如玩家身上存一个字段under_battle,如果下线时不在对战中这个字段就是0,如果在对战中就存断线时所在的battle id,然后上线的时候根据这个under_battle去battle manager查询这场对战的状态,如果是“正在进行中”并且其他限制逻辑都符合就把玩家加入对战,如果是“已经结束”就提示玩家说之前的对战已经结束了,你个倒霉孩子掉线了所以输了巴拉巴拉之类的。

第二种就比较有意思了。既然玩家只是短时间断线,那其实我们是可以做出更好的体验的,比如我们可以在玩家断线重连回来之后给玩家一种错觉就是他根本没有掉线,只是“卡”了一下而已。实际效果可能看起来就是,玩家在城市里跑着跑着突然断网断了1秒(由于什么wifi切换移动网络,移动网络基站之间互相切换之类的),然后他的客户端卡住1秒,并没有任何提示他断线,他也不知道断线了,之后他的客户端可能突然快进了一下这一秒应该发生的事情,这样给玩家的感觉会好很多,不至于说从家里出来wifi切换到移动网络就掉线要重新登录什么的。

实现上,云风大侠之前有个想法来提高移动网络的稳定,xj可能是基于云风这个想法然后结合他们游戏于是用go写了个反向代理服务器来做这个断线重连。原理可以直接看goscon项目的readme,写得很清楚了,再不行看代码,这里不赘述了。当然这种实现也有一点不太好的地方,就是goscon不仅仅是个proxy,还要实现负载均衡。但是仔细想了想,这个负载均衡是避不开的,只要的你是multi-server的这种架构方式,为了保证client-server之间断开重连的时候不会连到其他server上,连到其他server我们想要实现补发遗漏数据就会变得很复杂,也不能做到TCP连接的复用。

目前了解到的游戏断线重连差不多就是这样吧,还不知道是否有其他更好的solution。