御龙在天掉线问题定位过程

1.前言

掉线是令每个网络游戏开发人员头痛的问题,太频繁的掉线会影响玩家的体验从而影响到整个游戏的口碑。御龙在天是琳琅天上工作室自研的一款国战型的MMO网络游戏,在2012年公测初期,御龙服务器全体开发人员也被掉线这一问题困扰,通过大家长期坚持不懈的定位,掉线问题逐渐下降,给了玩家一个好的体验,获得了玩家的肯定与喜爱。

2.定位工具

御龙在天是基于互娱的tsf4g框架开发出来的,我们就是使用tsf4g里的tconnd作为链接层。Tconnd如果检测到链接层的异常,它就会给gamesvr发回一个TFRAMEHEAD_CMD_STOP消息,我们就是在gamesvr中接收和处理这个消息,并记录玩家掉线的日志。这些日志对于判断玩家掉线的原因非常有用。

在服务器上抓包,就是使用tcpdump命令。但是现在服务器端都接入了tgw,导致要抓特定玩家的链接的包变得困难了。

另外,有时候需要在玩家的电脑上进行抓包分析,刚开始时我们是通过QQ远程操作玩家的机器,安装WireShark并进行登录抓包,但是这样操作效率比较低,所以后面我们基于winpcap开发了一个御龙专属的抓包工具,玩家只需要直接运行这个工具,就可以抓到和御龙客户端相关的所有链接的包,并保存成文件。玩家只需要把生成的文件发回给我们,我们就能分析到玩家的网络状况。

3.经典掉线问题分析

由于国内的网络比较复杂,所以掉线的原因五花八门,像一些某地区的网络波动导致的掉线我们就不进行描述了,下面主要是挑选了我们遇到的2个比较经典的掉线问题进行分析,希望能对其他项目有些启发作用。

3.1 zone引起RST

御龙在天的定位是一个大型的国战类游戏,一个服是由9个国家组成,每个国家有N张地图,单服需要支撑7万人同时在线。由于它宏大的世界观,所以我们使用了机器集群的方式,图1就是御龙的单服架构图的简单表示。(如果想详细了解御龙的后台架构,可以在KM上搜索alancai的《御龙在天服务器性能优化小结》以及rosickyxiao的《御龙后台架构演进之路》)

1

如果玩家要从一个国家到另外一个国家,那在服务器端就是需要从Zone_A切换到Zone_B。切zone流程是这样的:

(1)Zone_A通过world_login转发一个切zone请求的SS消息到Zone_B

(2)Zone_B到对应的Tconnd_B上请求预分配位置,Tconnd_B如果预分配成功,就把相关的信息返回给Zone_B

(3)Zone_B通过world_login把这些信息返回给Zone_A

(4)Zone_A把当前玩家的数据回写DB并且组建一个通知包,把预分配信息下发给客户端,并同时通知Tconnd_A断开和这个玩家的链接(即在这个通知消息的TFrameHead中带上TFRAMEHEAD_CMD_STOP标记);

(5)客户端收到这些预分配信息后,就会使用这些信息去重连Tconnd_B,从而实现了跳zone,到达另外一个国家。

在御龙公测初期,外网一些玩家报出国偶尔会掉线。经过分析,他们都是被断开了当前zone的链接,但并没有连到新的zone上去。通过在玩家的机器上抓包分析,发现玩家是收到了一个RST包,并没有去重连新的zone。通过与tsf4g的同学一起定位和模拟试验,发现如果是服务器主动关闭链接,而这时候这个链接的发送缓冲区里还有消息没发送,应该是会把消息发送完之后才完全关闭的。但是如果服务器主动关闭后,这时候如果客户端还有消息发送上来的话(因为客户端不知道服务器已关闭,并且服务器关闭时客户端可能有些消息正在路上),那么这个TCP链接就会清掉发送缓冲区里还没发送的消息,并且直接给客户端发送一个RST,导致客户端没接收到最后那个跳zone通知包,而导致掉线。

对于这个问题,tsf4g的同学给我们的建议是让客户端来主动断开链接。但是由于御龙服务器的一些特性,我们最后并没有采用他们的建议,而是使用了下面的2种改进措施:

(1)在跳zone开始的时候(即上面的第(1)步),服务器先给客户端发送一个准备跳zone通知包,客户端收到这个通知包后,就把玩家锁定不给操作,并且不再发送消息给服务器。如果客户端收到服务器的跳zone错误通知包,或者超时了还没收到服务器的跳zone通知包,那就给玩家恢复正常,玩家可以继续在本zone进行游戏;

(2)给玩家发送跳zone通知包时(即上面的第(4)步),不要同时断开这个玩家的链接。为了节省内存,我们依然是把玩家的数据回写并且从zone的共享内存上释放这个玩家的对象。但是把这个玩家对应的TFrameHead信息保存下来(TFrameHead相对比较小),延迟一两秒后才加上TFRAMEHEAD_CMD_STOP标记并发送给tconnd,让tconnd断开相关链接。

做了上面2步优化之后,通过统计全服的掉线日志,发现由于跳zone而引起掉线的问题已经变得很少了。依然存在的那小部分跳zone掉线,就是玩家的网络条件比较差,是属于不可避免的问题了。

3.2发送缓冲区满

另外一个有意思的掉线问题,是我们服务器内部人员在新服体验游戏的时候发现的。跟踪掉线日志,发现是tconnd检测到链接的发送缓冲区满而主动断开的,同时在tconnd的日志里搜到这样的记录:

(tconnd_sendto_lisinst)] Inst[1922] of uin[173801489] send package to client [183.58.222.148:55696] failed!datelen[1282],iRet[1224],errorstring[Success]

从上面的日志可以发现,tconnd要向客户端发送长度为1282的消息,但调用send只发出了1224个字节。但是tconnd是不做消息缓存的,所以它就粗暴的断开链接并且给zone返回一个错误消息。

发送缓冲区满,我们立马就想到2个原因:(1)发送缓冲区太小;(2)玩家网络太差,丢包或延时严重,导致已发送出去的包得不到及时的确认。第(1)点马上就被我们否定了,因为我们在tconnd.xml里配置的发送缓冲区是1M,见图2a)。如果传入的值(1049000)没有大于允许的最大值(图2b)中的4194304),setsockopt函数会把缓冲区设置为传入的值的2倍,即1049000*2=2M2M的发送缓冲区是足够的。至于第(2)点,我们是在公司登录游戏的,网络不会差,同时也ping过,发现延时很小。

(a)

(b)

2

接着,我们关注到了机器的内存使用情况,发现zone所在的机器(老C1)的内存使用到了7点多G,几乎用完了。由于每个链接的发送缓冲区空间不是在创建链接的时候一下子分配出来的,而是在使用过程中逐渐增大的。当时就怀疑会不会是由于内存紧张,导致某些链接扩大发送缓冲区失败,导致只能在当前剩余的发送缓冲区上发送部分字节?或者是由于内存不够,而底层的系统调用也需要内存,需要等待SWAP OUT获得新内存使得处理速度变慢,导致缓冲区满?针对这2个疑问,当时google查了一些资料以及咨询了tlinux相关的同事,但是都没得到确定的答案。于是我们就决定把几台8G的老C1机器替换成16G的新C1机器,再观察对比下效果。

3就是最后对比出来的结果,其中标红的zone2zone6zone12zone16就是替换成16G的新C1。第3列的数值,是一整天里由于发送缓冲区满而掉线的数量。可以看到,换成16G的新C1后,这个掉线数量的确是减少了很多,一个zone一整天才几十个掉线,这个数量是比较令人满意的。

3

正当我们沉浸于以为找到原因的快乐的时候,一个系统参数走进了我们的视线。图4a)是老C1机器的参数,图4b)是新C1机器的参数。在net.ipv4.tcp_wmem里有3个数值,分别表示TCP发送缓冲区的最小值、默认值以及最大值。但是有另外一个参数net.core.wmem_max在新老C1机器里是不同的。这个参数是什么意思呢?

(a)

(b)

图4

通过写了个小代码进行测试,最后发现在setsockopt设置SO_SNDBUF时,net.core.wmem_max是替换了tcp_wmem里的第3个数作为最大值限制的。那这个问题的根本原因终于浮出水面了,是系统参数给限制住导致没能成功的把发送缓冲区设置为2M。虽然在tconnd.xml里配置了SendBuff1M,但在setsockopt的时候,是不可能把发送缓冲区大小设置为2M的,因为net.core.wmem_max限制了传入setsockopt的参数不能超出131071。所以最后设置的发送缓冲区大小只是131071*2=262142=256KB。只有256KB的发送缓冲区,肯定是不能满足一个MMOG的要求的。于是我们另外找了几台老C1机器,把这个系统配置改成2048000,再对比下,见图5。其中蓝色的zone1zone7zone11zone17就是把net.core.wmem_max设置为2048000,可以看到修改参数后,这4zone由于发送缓冲区满引起的掉线马上减少了很多,和16G的几个zone达到一样的水平,从而确定了是系统参数的问题。

5

4.结束语

经过御龙服务器全体人员坚持不懈的努力,现在御龙在天的掉线已经比较少了,玩家可以在游戏内得到好的体验。这是御龙服务器全体人员共同努力的结果,我只是负责整理,如果有疑问可以咨询我或者御龙服务器其他人员,谢谢!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值