使用locust测试百万并发TCP连接

背景

最近数据中心SDN项目有一个测试需求,要测试OVS-DPDK百万TCP连接支持情况。OVS使用有状态ACL时,它会感知和跟踪TCP连接,所以有测试最大TCP连接数目的需求。
jmeter每个htttp user是一个线程。Locust每个http user是一个协程。所以相同的资源条件下locust能模拟的http user数目远超jmeter。
Locust基于使用epoll的libev来实现socket的IO复用,基于greenlet实现高效的协程切换。

安装 

locust是基于python开发的,所以首先安装python。然后pip install locust安装locust。

本次测试版本信息

vm linux kernel 3.10,nginx 1.20.1,python 3.8.10,locust 2.13.1。

测试设计

locust做http客户端,nginx做http服务端。
测试拓扑:
locust-(vm)-OVS-DPDK-1-(server1)-------OVS-DPDK-2-(server2)-nginx
server1上,创建17台4核8G的vm。1台vm运行locust的master,16台vm运行locust的worker。
server2上,一台8核16G的vm运行nginx。
locust master只负责下发任务给locust worker,接受统计和展示,并不向nginx发起连接。
每个locust worker建立62500条TCP连接(TCP端口空间是64k),16台worker vm共计发起100万条连接。

环境配置

为了减少数据通信量,修改nginx vm上/usr/share/nginx/html/index.html的内容为:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <title>Welcome to CentOS</title>
</head>
<body>
</body>
</html>
共128字节长。

为了增加支持的连接数和让nginx保持持久连接,修改nginx配置文件/etc/nginx/nginx.conf的内容为:
user root;
worker_processes auto;
worker_rlimit_nofile 1024000;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;

events {
    use epoll;
    worker_connections 1024000;    
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   1024000;
    keepalive_requests  1024000;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    server {
        listen       8080;
        listen       [::]:8080;
        server_name  _;
        root         /usr/share/nginx/html;

        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }
}

locust的master和worker vm上都创建locustfile.py,内容为:
from locust import HttpUser, task, constant
class HelloWorldUser(HttpUser):
    wait_time = constant(900)
    @task(1)
    def get_index(self):
        r = self.client.get("/")
主要动作是每个user每隔900秒发送GET请求主页。因为并没有调用r.connection.close()来关闭连接,所以locust保持长连接。

nginx vm和locust worker vm上修改协议栈相关参数。主要是为了增加支持的最大连接数,同时捎带增加了新建连接能力、数据收发能力。

sysctl -w net.ipv4.tcp_timestamps=0
sysctl -w net.ipv4.ip_local_port_range='1024 64000'

sysctl -w net.core.somaxconn=32768
sysctl -w net.ipv4.tcp_max_syn_backlog=262144
sysctl -w net.ipv4.tcp_syncookies=0

sysctl -w net.ipv4.tcp_max_orphans=262144
sysctl -w net.ipv4.tcp_max_tw_buckets=5000

sysctl -w fs.file-max=10485760
ulimit -n 1024000
ulimit -u 2048000

sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216
sysctl -w net.ipv4.tcp_rmem='32768 131072 16777216'
sysctl -w net.ipv4.tcp_wmem='32768 131072 16777216'
sysctl -w net.core.netdev_max_backlog=262144

nginx vm上重启nginx服务:
systemctl daemon-reload
systemctl restart nginx 

如果nginx worker能够使用的文件描述符仍然是缺省的1024个,则创建文件/etc/systemd/system/nginx.service.d/override.conf,写入内容:
[Service]
LimitNOFILE=1024000
LimitNOFILESoft=1024000
然后重启nginx服务。

测试实施

server1 vm0上,运行locust master,等待woker数目达到16个时,一起开始建立连接,总共模拟100万http用户,spawn rate是1600user/second。即每个worker模拟62500个用户,每个worker的spawn rate是100user/second,所以大约625秒后,连接总数达到100万。
这里nginx vm的IP地址是192.168.102.2。
locust --headless -u 1000000 -r 1600 -H http://192.168.102.2:8080 --master --expect-workers 16

server2 vm1-vm16上,运行locust worker,选项master-host指定locust master vm的地址。
locust --worker --master-host=192.168.101.6&

测试结果

开始加压625秒后,连接总数达到100万。然后保持连接。
locust master vm上可以看到输出
Type     Name  # reqs      # fails |    Avg     Min     Max    Med |   req/s  failures/s
--------||-------|-------------|-------|-------|-------|-------|--------|-----------
GET      /    1000000     0(0.00%) |     90      30    3411     74 | 1594.50        0.00
--------||-------|-------------|-------|-------|-------|-------|--------|-----------
   Aggregated 1000000     0(0.00%) |     90      30    3411     74 | 1594.50        0.00
100万请求全部成功。

ngxin vm统计连接数:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED 1000000
建立了100万条连接。

开始加压900秒后,开始第二轮HTTP request的发送。第二轮request仍然使用前面建立的连接。
根据RFC3511 5.2 Concurrent TCP Connection Capacity的要求,应该在所有连接建立完成后,再发送一轮http GET,用于确认所有连接都建立后,仍然都能够正常工作。所以如果想要更严谨,可以等待第二轮request发送完成之后,再次检查locust master的输出。200万请求全部成功,测试就通过了。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值