600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 【python】HTTP压力测试过程中遇到的问题与解决方案

【python】HTTP压力测试过程中遇到的问题与解决方案

时间:2019-05-15 09:53:55

相关推荐

【python】HTTP压力测试过程中遇到的问题与解决方案

记录一下测试过程中遇到的问题

背景

被测试HTTP服务在容器中运行,使用的是gunicorn,在另外一台server通过python requests做压力测试

问题1. urllib3 connection pool full

urllib3.connectionpool Connection pool is full

requests使用了urlib3,urllib3中有PoolManager,它会复用连接,所以如果压测过程中,大量发起requests,会导致PoolManager中的connection pool满掉,进而出现这个问题。

【解决方案】

根据你的量适当调整pool_connections的值

session = requests.session()adapter = requests.adapters.HTTPAdapter(pool_connections=1000, pool_maxsize=4000)session.mount("http://", adapter)

问题2.Too many open files

Failed to establish a new connection: [Errno 24] Too many open files

每一个连接会打开一个socket,一个socket会使用一个句柄,可以通过ulimit -n查看当前系统的open file

默认是1024

在做压力测试的机器上,需要修改该值

【解决方案】

ulimit -n 65535

注:不过这个值只是在当前session中做了修改,如果下次登陆时还需要再做修改;

问题3 requests.exceptions.ConnectTimeout

客户端大量连接出现Connect timeout错误

原因有两个:

客户端的connect time设置时间过短服务端的syn backlog设置过小

【解决方案】

客户端的connect time设置,这里主要是requests库里配置超时的地方注意一下

requests.post(url, data=data, headers=headers, timeout=(CONNECTION_TIMEOUT, REQUEST_TIMEOUT))

服务端有2个参数可以配置

netdev_max_backlog

位置/proc/sys/net/core/netdev_max_backlog,主要控制当kernel无法及时处理时接收到的packets的队列大小tcp_max_syn_backlog

位置/proc/sys/net/ipv4/tcp_max_syn_backlog,tcp协议栈在收到客户端发送的SYN消息后会回复SYNACK同时将此消息放入队列,等待客户端发送ACK确认

问题4 requests.exceptions.ConnectionError:Connection reset by peer

'Connection reset by peer'

在客户端,大量的tcp连接被reset了,这里我们需要检测被测试系统的tcp backlog值是否足够,如果不够,服务连接达到瓶颈时,可能会出现该问题。

【解决方案】

tcp的backlog主要有2个地方配置

listen backlog

应用服务的tcp listen时,有一个参数是backlog,作为服务端,这个值不可以过小,请根据服务器物理性能适当设置

somaxconn

位置/proc/sys/net/core/somaxconn,控制ESTABLISHED的接连数量。 一些系统中默认是128,作为服务器显然是不足的,需要往上调整。 注意,如果不调整somaxconn,仅调整listen函数中的backlog,最终的结果是无效的。

比如listen函数中的backlog中设置1024,但是默认的somaxconn=128,实际上还是128.

问题5 Possible SYN flooding

通过dmesg -T查看系统消息时,如果有如下消息

TCP: request_sock_TCP: Possible SYN flooding on port xxx. Sending cookies

是大量SYN消息收到了,存入了SYN-ACK队列,但是没有被处理。

这可能是因为tcp的backlog设置过小,或者服务器处理性能不足导致的;对于前者请参考问题4解决方案,后者请优化服务性能。

问题6 requests.exceptions.BrokenPipeError

压测客户端出现如下报错

[Errno 32] Broken pipe

查阅资源是当往一个已经close的socket写时,会收到SIGPIPE。

This might be happening when a client program doesn’t wait till all the data from the server is received and simply closes a socket (using close function).

产生这个问题的原因是,我在线程中post数据,但是再压测程序最后的主进程中,在线程socket未结束的时候,直接close了socket。

其他注意事项

在docker以镜像方式部署的时候,请检查一下所用镜像中的系统配置,

比如:

open files是否是默认的1024?这个值肯定是过小的;

上述几个backlog参数是否是默认值?

一般镜像中的系统配置是只读的,需要在docker run的时候通过携带参数的方式来修改

比如修改somaxconntcp_max_syn_backlog的方式如下

docker run --sysctl net.core.somaxconn=2048 --sysctl net.ipv4.tcp_max_syn_backlog=4000

如果是使用docker-compose方式来启动的可以在yaml文件中添加如下

sysctls:net.core.somaxconn: 2048net.ipv4.tcp_max_syn_backlog:4000

或者

sysctls:- net.core.somaxconn=2048- net.ipv4.tcp_max_syn_backlog=4000

注:

netdev_max_backlog参数在容器中是没有的,只能修改宿主机配置容器里的参数与宿主机的参数不冲突,如果两者不一致以镜像中的参数为实际运行结果

检测tcp状态

可以通过脚本实时检测tcp的状态变化

下面是我写的脚本,用于检测服务端口,这里我的服务端口是5000

脚本print_tcp_conn_stat.sh, 内容如下,

#!/bin/bashecho "TIME_WAIT :"`netstat -tuna | grep 5000 | grep "TIME_WAIT" | wc -l`echo "ESTABLISH :"`netstat -tuna | grep 5000 | grep "ESTABLISH" | wc -l`echo "CLOSE_WAIT :"`netstat -tuna | grep 5000 | grep "CLOSE_WAIT" | wc -l`echo "SYN_SENT :"`netstat -tuna | grep 5000 | grep "SYN_SENT" | wc -l`echo "SYN_RECV :"`netstat -tuna | grep 5000 | grep "SYN_RECV" | wc -l`

然后使用watch命令,来做实时监控,

# 每1s监控一次watch -d -n 1 ./print_tcp_conn_stat.sh

效果如下,

这几个状态说明一下:

TIME_WAIT

客户端结束时,socket的状态ESTABLISH

tcp连接建立后的状态CLOSE_WAIT

服务端结束时,socket的状态SYN_SENT

客户端发送SYNSYN_RECV

服务端接收SYN

使用keepalive优化服务能力

如果你也使用gunicorn,可以在启动gunicorn的命令中添加如下参数,

gunicorn--keep-alive 30

使用了keepalive之前,每一次tcp访问,都会经理SYN_SENT -> ESTABLISH -> CLOSE_WAIT过程

(因为我客户端也复用了连接,所以没有TIME_WAIT)

使用keepalive后,服务器建立连接后,状态会一直保持在ESTABLISH,直到keepalive的timeout到了之后,服务端才结束连接,出现CLOSE_WAIT

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。