作者介绍:Robben,腾讯高级开发工程师。工作多年,长期从事后台的开发、架构设计、优化等方面的相关工作。商业转载请联系腾讯 WeTest 获得授权,非商业转载请注明出处。

WeTest 导读

对技术人员来说,知其然还需知其所以然——搞清技术的底层机制、弄明白问题的深层次原因、知悉解决方案的适用场景,是每个开发人员应有的技术素养,也是个人发展上积累功底、产品生命上维持稳定所必须的。

问题背景

8 月推送的《当压测遇见奥运 ——游戏服务器如何在上线时面对用户的洪荒之力》中提到了机器人模拟测试是对各类已有的压力测试方法做了一个平衡, 通过高还原真实玩家的用户行为,模拟高并发场景,从而得到类似很多人同时游戏的测试效果。
其中通过模拟机器人测试有四个优势:
1、 高还原游戏玩法,深度模拟真实用户行为;
2、 并发性不受限制,从 1W 到 10W,压力能够自主设置;
3、 可以反复执行,便于性能调优回归;
4、 实现 7*24 小时不断监控。
在开发提交代码之后,版本在自动编译之后就跑新的测试,这样每天都能进行性能监控,在调优方面,完全的进行一个重复性测试,可以不断的进行回归和调优。这个方法的问题就在于机器人模拟需要专人开发,对测试者的开发能力,分析能力都有一个比较高的要求。

而要开发一款进行服务器性能测试的机器人,需要通过建模、分析、开发三个步骤,那么今天我们就要来介绍一下,具体在开发服务器性能测试机器人的时候,如何让它表现的更像人?有更加平稳和正常的表现?

为了让介绍的内容更加形象和具有说服力,我从我们自己的产品开始介绍,扒一扒腾讯 WeTest 服务器性能测试在开发机器人的过程中遇到的一些坑。

WeTest 平台的服务器压测,支持用户在一个测试用例中定义递增的机器人数量,通过逐步增压的方式,来探索服务器的实际承受能力。从下图的机器人压力曲线图可以获取直观的概念:

曲线统计的是每个时刻连接到服务器并且进行业务数据收发包的在线机器人个数,由曲线看上去,可以感受到压力是平稳递增的(中间有微小下跌,是因为当前的模式下,会在不同的阶段更新和重启机器人,这个也是后面会优化之处)。然而,为了在测试结果报告中画出这样一张合理的图,也是经历了几番折腾,总结一下,还是蛮有意思的。

优化历程

对于上图描述的同一个压力逐渐递增的测试用例,经过了许多版本的迭代才能得到最终的效果,最早版本的机器人压力曲线,统计生成后出现了这样的问题:

【问题】模拟机器人在开始的十几秒内,压力还算有些头绪,后面某个时刻,就经历了急剧的下跌,之后就完全无规律可循了。

【分析】经过定位,这个阶段的问题是,我们的压力测试工具在响应包较大时,会出现接收缓存区数据被并发写入而数据污染的情况,导致程序 core 掉。经过快速的修改调试,问题终于被修复。OK,压力曲线应该会比较平稳了吧。

然而理想很丰满,现实很骨感,模拟机器人依然存在问题:

【问题】在大概二十秒内的时间,还是比较平稳地增增减减,维持在一个稳定的水平。然后到二十秒后,又会出现急剧地下降,压力上不去,大概半分钟后,反扑,上升,没多久再急剧下降。。。

【分析】首先查看压力工具的运行逻辑,一切正常;程序,没 core,一切正常;日志错误,没有,一切正常。那压力为何上不去呢?查看系统的各种运行时数据,终于发现了问题所在:

原因 1:由于咱们的机器是部署在合作伙伴腾讯云这里的,机器拿到后也并未进行大的配置调整,所以系统默认可用的端口范围还是比较小的,如下图:

而作为一个模拟机器人的压力机,必然会在短时间内并发和服务器建立大量的连接,所以本地的端口号是必须大一点的,直接改文件,增加范围,搞定:

原因 2:其实就是经典到有些老生常谈的 TCP timewait 问题了。因为我们压力机的机器人,会并发建立很多短连接,并且每次都由机器人主动断开短连接,所以导致系统中存在大量的 timewait 连接。直接结果就是没法建立新的连接,在线机器人数量上不去。

这里简单地提两个要点:
a) timewait 是在 TCP 连接的主动发起方才有的状态,一句话概况,它是为了防止 “主动断开连接方发送的最后一个 ACK 包异常,导致被动关闭防会重发 FIN 请求,影响该四元组上的下一个连接的正确性” 这一问题而设计的,通过主动关闭方等待 2*MSL,即两倍的报文生存期的时长来避免。如此,报文一来一回的时间都等完了,大概率保证了确实没异常了。继而,系统中也就常常会出现大量的 timewait 连接。

b) 解决的方法,一般是把两个内核参数:net.ipv4.tcp_tw_recycle、net.ipv4.tcp_tw_reuse 都改为 1,前者指启动 time wait 连接的快速回收,后者指让 time wait 的四元组可以快速用于新连接。
然而两个优化都是有需要注意之处的:
对于第一个参数,当它置 1 后,为了解决 timewait 设计时出发点的风险,新来的连接请求在如下情况会被拒掉:同一客户端 IP 在某时间窗内的新连接时间戳变小。虽然一般是不会存在这种情况的,但是,对于 NAT 而言,则天然容易出现这个问题:A 连接服务器 -->B 连接服务器 --> B 先被 accept --> A(同一 NAT IP)请求到了服务器 --> A 请求被据。
对于第二个参数,一般认为,它不太能解决纯服务端的资源占用问题,因为四元组虽然能用了,但资源还是没释放;但对于有客户端性质的情况是适用的,如连接 mysql 的服务端 php 进程。
了解了这些之后,我们的压力机,既不存在要响应 NAT 过来的客户端请求的情况,又不存在服务器端的特点,所以天然是非常适合用这两个内核参数的优化的。
经过这一轮系统参数的优化后,在线机器人数量基本稳定了:

因为是短连接,所以在线机器人的数量曲线并不是水平的,但至少可以一直保持较高的并发。更进一步,我们在产品的实现层面又做了优化,开放长短连接配置给用户,同时对于 HTTP 协议的简单模式,仿照真实的浏览器行为,将默认行为置为长连接。这样,就会出现文章开头的理想曲线了:

总结感受

其实本文中的优化只是非常小的一个点,也没有什么惊心动魄的过程与艰深晦涩的理论,几轮优化着手点涉及的概念范畴也杂,但却是一个真实的逐步解决问题的典型。
在这个网络发达,信息爆炸的时代,基本上对于每个技术点或者问题,都可以迅速地获取到大量资料。关键是对于技术的实现原理和问题的解决方案,却不能仅仅知其然,还必须知其所以然——搞清技术的底层机制、弄明白问题的深层次原因、知悉解决方案的适用场景,是每个开发人员应有的技术素养,也是个人发展上积累功底、产品生命上维持稳定所必须的。

而腾讯 WeTest 的压力测试团队正是运用了沉淀十多年的内部实践经验总结,通过基于真实业务场景和用户行为进行压力测试,推出一套面向游戏业务的综合性应用性能管理解决方案,该方案旨在帮助游戏开发者发现服务器端的性能瓶颈,进行针对性的性能调优,降低服务器采购和维护成本,提高用户留存和转化率。

目前腾讯 WeTest 服务器性能测试已经正式对外开放,业务场景模拟,持续压力触达服务器极限,帮助寻找服务器性能问题!点击链接:http://wetest.qq.com/gaps/立即体验!


↙↙↙阅读原文可查看相关链接,并与作者交流