转自: https://mp.weixin.qq.com/s?__biz=MzIxMjAzMDA1MQ==&mid=2648946009&idx=1&sn=3a0be2fe4f098de819f7dc05b79c593f&chksm=8f5b5255b82cdb43fa8714aed8c351306596492396467bf85d8e14ee476e944e5e58bb0ba724#rdgit
作压力测试的时候但愿能够在服务器上采样,能得到当前服务器的TCP链接数、链接耗费时间的最大值、最小值、均值。github
TCP链接采样最直接的方式是经过netstat统计ESTABLISHED
状态的TCP链接数。通常压力测试工具会提供一份报告说明发送请求的最大值、最小值、均值。数组
netstat原理是读取/proc/net/tcp给出当前服务器的TCP状态,当“列表”很长的时候它就要花费更多时间完成解析。采样到的数据不及时,并且nestat会消耗很是大的CPU,影响测试结果;服务器
压力测试工具报告的请求耗费时间的最大值、最小值、均值包含了网络延时。压力测试工具会同时开启N个并发访问服务器,对于网络来讲是有大量的数据包同时产生,极可能受限于测试机或者服务器的带宽,根本没有送到服务器或者是测试机来不及处理产生了延时;网络
最好的办法是经过内核Hook拦截某些关键的TCP函数,好比能找到相似tcp_connect、tcp_close的函数。遗憾的是TCP创建链接比较容易找到(无非是accept、tcp_v4_connect之类的),可是关闭部分却没有相应的函数。这个问题折腾了我很多时间,最后我借鉴了nestat的思路——经过TCP的状态判断。并发
至于Hook内核基本上没什么难度,祭出大杀器Systemtap就好了。tcp
Systemtap是世界上最牛B的Linux内核调试工具(没有之一),若是你以前据说过DTrace那么能够把它理解为DTrace for Linux。使用它经过简单的几行代码咱们就能够Hook到内核中的任何函数,不但能够“截获”参数甚至能够修改参数。函数
我定义了一个全局数组connection
,当TCP状态是ESTABLISHED
时我会把时间戳放到以客户端IP地址+端口为Key的关联数组中,当TCP状态是CLOSE、CLOSE_WAIT时根据IP地址和端口取出时间戳,计算出耗费的毫秒数放入累加变量spend_time中。为了统计当前并发数,程序中每隔1秒钟,修改report关联数组。工具
最后在程序结束的时候输出全部请求耗费时间的最大值、最小值和均值。学习
经过ab简单的模拟一下效果,设置并发度300,总的请求数量是10000。
结果显示ab记录发送了10000次而实际上服务器多收到146次,这部分请求应该是ab认为失败其实已经成功的。服务器的峰值是179,远远没有达到300的并发度。
附上systemtap脚本地址
https://gist.github.com/fireflyc/cf82f27ebbfe1ff61c4f789b8b1b0d25
这篇文章的目的实际上是想让你们学习用systemtap。网上关于它的教程不少,因此再写一篇“教程”也不可能好到哪里去。因此介绍一个以前写过的一个脚本,但愿可以抛砖引玉。
欢迎关注公众帐号了解更多信息“写程序的康德——思考、批判、理性”