今天遇到一个性能压测的问题,也是很多同学做游戏服务器开发经常会遇到的,今天记录一下分享给大家。
性能压测遇到的问题
服务器硬件情况:
8核16G服务器, 带宽1000M, redis假设在独立的内网云服务上,通过内网连接;
性能压测:
压测功能接口1: 查询当前服务器的时间戳,并返回给客户端;
压测功能接口2: 给定key, 查询redis服务器hash表中的一个value,并返回客户端;
压测手段,并发2000次请求;
测试功能接口1结果: (并发2000,TPS 16000,RT 20ms)
测试功能接口2结果: (并发2000,TPS 6000, RT 3000ms)
压测问题:
为什么并发2000,查询一个redis 结果需要等待3秒, TPS 下降到6000,哪里的问题? 如何优化?
附:
RT: Response Time, 从发送请求到获得结果的响应时间,包括了Request Time, Response Time。
TPS: Transactions Per Second, 每秒处理的事务数。
性能分析之基本情况调查
遇到这类问题,我们首先要做问题分析,在处理问题之前,一定要了解清楚并发时候的服务端技术架构组成,以及相关信息,然后再对问题做出对应的判断与调试。我思考了一下,先问了一些相关的问题如下:
问题1: 做并发测试时,服务器的架构是如何的?如何部署的?
首先就要搞清楚,当前服务器架构是多少个线程or进程, 如何并发的?能否发挥多核的优势。
目前服务端架构是基于Java技术,网络请求基于Java的Netty, 逻辑处理接口采用多线程来进行处理。处理线程与Netty IO线程是分开的。目前IO线程为4个,处理线程为8个。
问题2: 目前极限测试的情况下各CPU以及硬件设备的占比情况如何? (CPU, 内存,IO, 网络带宽)
CPU: 目前CPU占用率约为20%;
内存: 目前内存的使用为1G左右, 内存稳定;
磁盘文件IO: 测试的时候没有文件读写等IO操作;
网卡占用: 目前回复的都是不是大量的数据,网络带宽占用很低;
问题3: Redis服务器情况如何?
Redis服务器目前为独立的,Redis服务器的资源占还很充足,目前未发现有太严重的性能问题。
问题4: 停掉并发, 单独响应redis的时间未多少?是否正常?
停掉并发后,客户端向服务端发送一个redis 查询的请求,大概响应时间为40ms左右。算上来回的网络时间,是正常的。
问题5: 在服务器向Redis服务器做一次redis查询多久?
这里在服务端代码中打印,向Redis服务器查询一次hget大约需要1ms左右。
为什么要问这些问题呢?这个是解决性能问题的关键的一些依据,根据这些依据我们来制定一些问题可能的方向。问题1了解服务端基本的架构与部署,能知道这个架构是否能充分的发挥目前硬件的性能。问题2,主要是了解服务器是否遇到了运行时的瓶颈,导致无法在提升并发性能。问题3,当前的性能测试与Redis有关系,排除掉Redis服务器的干扰。问题4,屏蔽掉并发后,看一下整个查询链路逻辑中是否有异常。排除掉一个请求中代码逻辑的问题。问题5, 测试服务端请求Redis的情况,彻底排除掉Redis的影响,因为本次的性能测试请求与Redis有关。
问题的分析与解决
经过上面的调查,我们总结了一下相关的情况,单次访问Redis正常,从请求到返回耗时大约是40ms, 说明整个链路没有大问题。
Redis查询业务时间=客户端发送请求到服务端时间+服务端查询Redis结果的时间+服务端发送回应到客户端时间。
过程中没有大规模的内存创建与释放,没有IO操作, 内存与IO不会为性能的瓶颈。Redis服务器一切正常,Redis支持的高并发一般不会有太大的问题。硬件的CPU占用率等都很低,并没有发挥出来完全的硬件,说明应该还有提升的可能。
假设单核情况下服务端处理业务,服务端向Redis服务器请求需要等待1ms的话,那么2000次并发就需要2秒。同时还需要接受客户端的请求+发送数据到客户端做网络IO,
40 ms, 假设网络传送时间来回各20ms, 1个核心1秒可以处理大约50个网络请求与返回。处理50个的时候,大部分CPU的时间都是在等待网络传送,所以虽然只能处理50个,但是CPU占用率不会很高。Netty开启了4个IO线程,所以,每秒可以处理大约为200个网络请求。2000次并发网络请求的时间大约是2秒。问题中,总共8个CPU核心,CPU占用率20%左右,要3秒的响应时间,和我们数据分析出来的基本能对上。从上面分析,我们可能是开的线程不够,导致处理redis的时候并发率上不来,是IO线程不够还是Task 逻辑处理线程不够呢?从简单的查询来推断,应该是逻辑处理线程不够。IO线程处理第一个网络请求的时候没有问题,说明IO线程数目是没有问题的。
大概估摸计算以后,我就让小伙伴加大逻辑处理线程与IO线程,然后对比,如图:
今天的分享就到这里了,问题比较简单,但是分析的思路值得推荐给大家,所以我就写了这个文章