《天天炫斗》弱网处理以及断线重连方案
当前手游现状
- 网络不稳定:购买道具半天没响应、切换副本版本不流畅、意外重复购买...
- 网络闪断:”又掉线又得重新登录“、”KAO,副本中掉了,前面的BOSS白打了。“...
弱网处理
- 客户端维护上行包的包序
服务器记录客户端最近一次上行包的包序,服务器通过判断包序来过滤已经处理过的请求。 - 服务器维护下行包的包序
客户端同样可以通过判断服务器的下行包包序来做对应处理,防止出现数值和界面异常的情况。
登录流程
《天天炫斗》首先是一个全区分服的架构, 前端逻辑层会有多个小区,每个小区会存在一组GameServer服务器,每个GameServer服务器自己会上报自己的负载情况到DIR服务器。
客户端登录的时候,首先会登录到DIR服务器拉取所有的小区列表,当选择某个小区登录的时候,又会拉取这个小区下的所有GameServer服务器。根据这个小区GameServer的负载情况,来挑选一台GameServer登录。
断线重连
首先客户端会记录上次登录的GameServer的IP和端口,断线重连后,是直连到GameServer的。如果GameServer还能够找到它的player对象是可以重连成功的。服务器这边每个客户端会为它保留player对象10分钟,在10分钟中之内重连的都是可以成功的。
断线重连有一个关键的地方是会做缓存处理,客户端重连会上报一次下行包包序,服务器根据这个下行包包序来判断是否给它下发在断线期间有哪些包重复下发下去,能够保证它的流程得以继续。
测试案例:客户端如果在进入副本之后,比如这个时候要进入电梯,客户端界面上会显示转圈,实际上它是在尝试重连,等到除了电梯的时候能够重连成功,那么在这个副本中流程也就可以继续了。这主要得益于在断线期间,能够保证所有的下行包在重连之后一次下发。
缓存机制
- 下行包缓存处理
存储结构设计,存储结构每个节点都有三个元素:下行包包序即序号(seq)、下行包大小(size)、下行包pack之后的二进制 (msgbuf),依次存入到内存中,向这个存储结构存储消息,只需要移动end buf这个游标。如果内存不够的情况,回收则移动begin buf游标。
- 下行包缓存流程
首先要判断下行包是否在黑名单中,比如一些服务器会踢掉客户端下线的下行包是不应该缓存的,然后要判断缓存是否足够,如果足够的话就依次将三个元素存入缓存中。内存不足的情况下就需要去移动起始游标来回收内存。
关键点
- 下行包都是经过pack之后存储,主要是为了节省内存的考虑。
- 缓存不足后移动起始游标进行回收直到回收的内存足够为止
断线重连流程:
首先从缓存中取出最旧下行包包序,与客户端重连上报的下行包包序进行比较。过滤较早的包序,然后在断线期间没有下发的下行包可以一次下发。如果客户端上报的下行包包序比较旧则会导致重连失败。客户端断线期间时间比较长的话会导致缓存中的包过多,也有可能导致客户端重连失败,比如前面的包已经被回收掉了的话,客户端这个时候重连就有可能失败。
关键点
- 客户端断线时间过长会导致缓存的包过多,则重连失败,防止UI异常。
- 过滤较早的下行包时不移动起始游标,客户端可能会再次重连。
断线重连统计
天天炫斗线上重连统计情况,抽取线上一台GameServer的统计结果。