【游戏】服务器性能测试(四) 简单压测工具理论篇
目录
阈值
架构容灾
一、前言
前面几期已经介绍了压测需要考虑的内容包括服务器的架构是怎样的、服务器承载指标有哪些、有做过哪些阈值防范等等。这期开始着手尝试介绍压测工具需要的知识点和设计思路。
二、压测工具设计思路
图1
图1做了一个简单的压测交互关系,对服务器压测需要大量的“真实”用户,每个用户都是独立与服务器进行协议通信。首先压测工具需要有网络模块的支持,目前大部分的游戏网络通信是基于TCP协议的,也有一些是基于UDP协议的。其次同时需要支持这么多用户运行,就需要考虑多线程模块。最后就是压测所需的并发控制与事务统计等功能。
1. 网络编程
压测的用户数会需要很多,少则三五千,多则上万。图1的用户与socket比例为1:1可以看出,创建socket的对象数量也会很大,而实际压测中很多情况下用户与socket比例可能会更高。因此网络编程就需要做好socket维护与管理工作,并且还需要具备高效率。最基础的可以采用I/O多路复用模型select对socket读写进行管理,其代码如下:
rbuf, _, _ = select.select([sock1,sock2,sock3,.....],[],[])
handler_all_active_sock(rbuf)
在Windows系统平台可以采用完成端口(IOCP)高并发模型替代select,在Linux系统平台下则可以使用epoll来替代。
2. 多线程
上面采用select模型时,默认只支持1024个socket对象,但是实际中创建的socket对象远远超过这个值,因此就需要分多个线程,每个线程里面保存一定数量的socket来规避这个问题如图2。虽然select模型的上限值可以修改,但select采用的是轮询的方式来判断每个socket是否可以读写,如果里面放入过多的socket对象,轮询就会带来一定的效率问题,另外每个socket读取数据也需要一定的耗时,如果放一个队列里面就会造成读取延时。
图2
是否可以对每个socket开辟独立的线程来进行读写呢?其实线程数并不是越多越好,线程过多就会产生过多的线程切换,从而会消耗CPU资源,一般总线程数建议不超过CPU核数*2。这块可以考虑使用线程池的设计方式。
3. 并发控制
将创建的用户放在一个队列里面,按照并发步长,每秒选取指定数量的用户执行并发请求,由于本身并发的消耗并不高,一般采用一个并发线程。遍历选取的用户列表每个用户执行一次协议数据请求即可如图3。
图3
4. 事务响应时间统计
每个用户在发送协议请求时记录下当前的时间(精确到毫秒或微妙),等待服务器返回结果后,计算出这次请求的耗时从而得到事务的响应时间如图4。可以看出事务响应时间包含了网络传输,服务器内部逻辑处理两部分。实际压测中一般保持压测工具与服务器在同一个局域网,从而减少网络延迟带来的数据影响。
图4
通过统计所有用户的事务响应时间,计算出平均响应时间,然后通过TPS=并发数/平均响应时间,即可得到该事务在当前并发下的TPS值。
5. 维持心跳
游戏客户端与服务器通常是长连接,在执行并发的时候并不会同时让所有用户一起发送协议请求给服务器,而是按照指定的并发,轮询分组选择指定数量的用户进行协议请求,其他用户则等待。但是服务器是不允许长期不活跃的用户存在,一般超时后就会主动断开这个连接,所有想要每个用户都可以保持正常在线,需要维持心跳,而且正式环境中每个客户端也是会与服务器保持心跳连接。
以上总结为下图5,并发线程控制每秒的用户并发,网络线程池用来管理每个用户的网络通信,定时器线程用于做一些特殊的业务,例如心跳维持。事务统计模块则根据用户的请求处理响应进行记录。
图5
三、工具开发中的一些难点
1. 业务流程梳理
游戏客户端与服务器通常是长连接,例如压测一个在商场购买物品的接口,首先需要将用户登录进入游戏,也就是跟客户端一样,从登录开始一步一步与服务器通讯,直到成功进入游戏后,才可以进行商场购买物品接口压测。因此对每个接口场景进行压测前,首先必须了解这个场景的流程情况,前置条件,判定接口完成条件等。
2. 网络通信复杂
压测的每个用户的流程必须与“真实”客户端接近,因此必须包含协议加解密,协议序号维持等。另外用户个人接口压测相对简单,但是涉及多人业务例如组队,联盟公会,匹配战斗等场景流程复杂,涉及面广,同时还必须保证在高并发下压测工具的业务逻辑能够正常运行。
广播相关业务压测需要高用户在线,压测工具必须保持多用户在线以及处理过高网络数据的压力,不过这类业务可以取巧来减少压力,就是少量用户并发压测,并在另一台机器上登录在线被广播的用户从而保证整体在线用户和并发压力。
3. 健壮的网络层
正是由于网络通信的复杂情况,假设网络线程本身是多线程的,线程同步问题又比较难弄,因此要写一个稳定健壮的网络底层需要花一定的时间。同时网络层还必须支持TCP和UDP两套协议,以保证适用不同的业务需求。
4. 业务与底层分离
压测框架基本上可以复用,但业务逻辑会根据不同的游戏而变化,因此也需要做到框架与业务分离,以在不同的项目中可以复用。这样就需要确认哪些是通用的,哪些则是当前压测游戏业务独有的,将变化的抽出来提供通用接口,封装不变的内容。从而达到框架的多项目适用性。
四、后记
这期主要介绍理论相关的东西,文字量有点多,如果真的想做好游戏服务器压测的话,还需要多花时间学习与实践,只有通过不断的尝试才能最终完成适合自己的压测工具。