tcpkali在github项目的地址如下:https://github.com/satori-com/tcpkali。
本文详述TCPkali的基本测试用法。TCPkali是一个可以用来测试四层TCP协议,七层HTTP(s)协议和websocket协议的测试工具。当然这个工具最主要的优点用的还是在于能够独立的进行TCP和websocket测试。
tcpkali可以支持在Mac OS,linux和UNIX上安装。博主在实操中所使用linux操作系统,这里主要详述centos7.x版本中的安装。
在tcpkali的github上推荐使用包安装的方法。但是博主亲自实验之后发现其实在国内包安装没有源码编译安装好用。centos操作系统中要直接安装tcpkali的软件包,需要用到nix工具。而安装nix安装管理工具之后,再去安装tcpkali的包会去nix国外的源去下载,经常访问超时导致安装失败。所以笔者不建议国内的玩家使用这种方式。这里仅给出安装所需的操作步骤
#安装bzip解压工具
yum -y install bzip2*
#访问nix官网下载安装nix安装管理工具,nix是类yum的安装包管理工具,可以通过nix安装可用的包。
curl https://nixos.org/nix/install | sh
#通过nix安装tcpkali的可执行的软件包
nix-env -i tcpkali
在国内笔者比较推荐使用编译安装的方式在centos的操作系统中安装tcpkali工具。其主要步骤如下
#以最小化安装centos7.5操作系统为例,yum列出了所需要安装的软件包。主要下载所需的编译软件,git安装工具,vim编辑工具。
yum install -y git autoconf automake libtool bison flex gcc-c++ ncurses-devel vim
#在git上拉取所tcpkali的源码
git clone https://github.com/satori-com/tcpkali.git
#切换到tcpkali的下载文件目录
cd tcpkali/
#检测configure文件并更新已经生成的配置文件
test -f configure || autoreconf -i
#编译安装前执行配置文件
./configure
#编译安装,安装完成之后可系统中就可以tab出tcpkali的命令
make && make install
-h, --help : 打印出tcpkali的帮助文档并退出。
–version : 打印出tcpkali的版本号并退出
-v, --verbose level :详细打印输出结果,可以增加-v参数的次数来表示详细信息程度。例如想打印更为详细的输出结果可以使用“-vvv”。也可以使用“–verbose 3”来表示打印输出信息的详细程度。默认的详细信息程度从0-3。
-d, --dump-one : 选择在任意的一个链接上打印出该链接输入或者输出的数据。当该链接被关闭时,将会使用其他链接来进行转储信息。主要用来诊断链接中收发信息是否符合预期。
–dump-one-in : 只转储单个连接上的输入数据。
–dump-one-out : 只转储单个连接上的输出数据。
–dump-{all,all-in,all-out} : 转储所有链接上的输入输出数据。
–write-combine=off : 单独发送消息而不是批量的写入消息. 该参数设置为off则暗示着 --nagle=off, 如果没有在命令行显示调用将其关闭,这该参数默认是开启的。
-w, --workers N : 要使用的并行线程数。默认值是根据需要使用尽可能多的内核,最多使用系统中检测到的内核数量。
–nagle=on|off : 通过使用setsockopt()设置TCP_NODELAY套接字选项来控制Nagle算法。默认情况下根本不调用setsockopt(),这使得Nagle在大多数系统上都是启用的。
–rcvbuf SizeBytes : 设置TCP接收缓冲区(使用setsockopt()设置SO_RCVBUF套接字选项)。此选项对具有自动接收缓冲区管理的某些系统无效。如果rcvbuf不起作用,tcpkali将打印一条消息。
–sndbuf SizeBytes : 设置TCP发送缓冲区(使用setsockopt()设置SO_SNDBUF套接字选项)。此选项对具有自动接收缓冲区管理的某些系统无效。如果sndvbuf不起作用,tcpkali将打印一条消息。
–source-ip IP : 默认情况下,tcpkali自动检测当前主机端口并使用所有可用接口连接到目标主机。这个默认行为允许tcpkali打开到目的地的超过64k个连接。使用**–source- IP 通过指定要使用的特定源IP来覆盖此行为。多次指定–source-ip**选项将构建要使用的源ip列表。
–ws, --websocket : 使用RFC6455规范进行WebSocket通信传输。
–ssl : 为客户端和服务器端连接启用传输层安全性(TLS,以前称为SSL)。
–ssl-cert filename : 使用X.509证书来进行TLS加密传输。 默认 “cert.pem”。
–ssl-key filename :使用私钥文件来进行TLS加密传输。默认 “key.pem”。
-H, --header : 添加指定HTTP包头到WebSocket握手中。
-c, --connections N : 打开到目标的并发连接数。默认值为1。
–connect-rate Rate : 限制每秒新连接的数量。默认值是每秒100个连接。
–connect-timeout Time : 限制尝试连接中花费的时间。默认值是1秒。
–channel-lifetime Time : 在设置的时间秒数后关闭每个连接。
–channel-bandwidth-upstream Bandwidth : 限制单个连接的上行带宽。
–channel-bandwidth-downstream Bandwidth : 限制单个连接的下行带宽。
-l, --listen-port port : tcpkali作为服务端接收指定端口上的链接。
–listen-mode=silent|active : 在接收到新建连接时执行操作。在静默模式下(silent),tcpkali不发送数据并忽略接收到的数据,这是默认值。在活动模式下(active),tcpkali向连接的客户机发送消息。消息需要由message参数指定。
-T, --duration Time : 退出并在指定的时间之后打印最终统计信息。默认为10秒(-T10s)。
–delay-send Time : 将发送字节延迟到指定的时间量。
-e, --unescape-message-args : 如在tcpkali命令行上使用了-m、-f或其他发送了流量内容的指定选项,则发送的消息数据不会进行转义。将\xxx序列转换为具有相应八进制值的字节,将\n转换为换行符,等等。
-1, --first-message : 首先发送此消息,在每个新建连接开始时发送一次。可以多次指定此选项,以便在每个连接开始时发送几个初始消息。如果–websocket选项被给出使用,每个消息都被包装到它自己的websocket框架中。
–first-message-file filename : 从文件中读取消息,并在每个连接开始时发送一次。可以多次指定此选项。
-m, --message string : 从文件中读取消息,并在每个连接开始时发送一次。可以多次指定此选项.
–message-stop string : 如果在接收到的字节流中遇到给定字符串,则终止tcpkali。
-f, --message-file filename : 重复地将从文件读取的消息发送到目标地址。可以多次指定此选项。
-r, --message-rate Rate : 在连接中每秒发送的消息数。tcpkali试图保留消息边界。此设置与–channel-bandwidth-upstream选项互不兼容,因为它们都控制消息发送速率。
-r, --message-rate @Latency : 不要指定消息速率,而是尝试计算不会导致超过给定消息延迟的最大消息速率。需要设置“ --latency-marker”延迟标记选项。
示例: tcpkali -m "PING" --latency-marker "PONG" -r @100ms
tcpkali可以测量TCP连接延迟,tcpkali会标记指定接收特定的字节。当接收到特定标记的第一个字节时计算时间和请求-响应延迟。
–latency-connect : 测量TCP连接延迟。
–latency-first-byte : 测量第一个字节的延迟。只适用于活动套接字。
tcpkali通过重复记录每次发送消息的时间(由-m或-f指定)与在下行流量中观察到延迟标记的时间(由–latency-marker标记设置)之间的时间差来度量请求-响应延迟。
–latency-marker string : 指定要在数据流中查找的每个消息的特定字符序列。
–latency-marker-skip N : 忽略掉前N个特定字符值,该字符由–latency-marker标记。
–latency-percentiles list : 报告指定百分比的延迟。该选项采用逗号分隔的浮点值列表。平均值和最大值可以使用 --latency-percentiles 50,100报告。默认是95、99、99.5。
00
–message-marker : 被动模式下的检查或消息标记。给定此选项,tcpkali将检测{message.marker}字节序列,并将计算消息速率(以每秒消息数为单位)和消息到达延迟。在活动模式下,通过隐式启动{message.marker}}表达式来计算消息速率。
StatsD 就是一个简单的网络守护进程,基于 Node.js 平台,通过 UDP 或者 TCP 方式侦听各种统计信息,包括计数器和定时器,并发送聚合信息到后端服务
–statsd : 启用StatsD输出。默认情况下禁用StatsD输出。
–statsd-host host : 将数据发送到指定的statsd主机上。默认是本地。
–statsd-port port : 使用StatsD端口。默认是8125。
–statsd-namespace string : 指定命名空间,默认是“tcpkali”。
–statsd-latency-window Time : 默认情况下,测量延时是在tcpkali运行的整个持续时间(由–duration或-T设置)内进行。此选项指示tcpkali每次将延迟数据刷新到StatsD并重新开始测量延迟的时间。在tcpkali整个运行过程中,用户界面中显示的延迟仍然被收集。
使用tcpkali需要关注的一点是如何打开想要的并发连接数。不难想象如果一个机器有一张网卡,网卡上配置了一个IP。那么这台机器和目标“IP:端口”所能建立的并发链接数就可以达到6.4W。如果有多个网卡的话那么就可以达到十万以上的并发。在执行压测之前需要对系统进行一些优化使其能够打开你需要并发链接。
vim /etc/security/limit.conf
* soft core unlimited
* hard core unlimited
* soft nofile 1024000
* hard nofile 1024000
#添加如下配置项,使root用户的最大文件数可到百万级别
root soft nofile 1024000
root hard nofile 1024000
vim sysctl.conf
#设置系统可打开的最大文件句柄数,该参数与第一步修改的用户可打开文件数相互作用
fs.file-max=130000 #这里给出的配置公式是:10000+2*N(N为你想打开的最大连接数)
net.ipv4.tcp_max_orphans=60000
#For load-generating clients.
net.ipv4.ip_local_port_range=1024 65535 #放开系统端口限制,可以允许使用1024之后65535之前的任意端口
net.ipv4.tcp_tw_reuse=1 #开启端口复用技术
就笔者实际使用tcpkali经验,tcpkali可以执行以下三种测试任务:
首先看一下tcpkali如何压测webserver。这里压测端是一个使用nginx搭建的静态页面webserver。tcpkali作为压力端虚机上有三张网卡,ip分别为10.130.1.71/24,10.130.1.11/24,10.130.1.110/24。nginx服务端只有一张网卡ip为10.130.1.217/24。
客户端使用单网卡压测:
#这里发送的消息转义之后就是一个GET请求
# tcpkali --connections 6000 --connect-rate 6000 -T 120s -em "GET / HTTP/1.1\r\nHost: 10.130.1.217\r\n\r\n" 10.130.1.217:80
Destination: [10.130.1.217]:80
Interface eth0 address [10.130.1.71]:0
Using interface eth0 to connect to [10.130.1.217]:80
Ramped up to 6000 connections.
? Traffic 220.537↓, 16363.188↑ Mbps (conns 0↓ 4262↑ 1736⇡; seen 21656)
等待测试执行结束之后打印出结果如下:
# tcpkali --connections 6000 --connect-rate 6000 -T 120s -em "GET / HTTP/1.1\r\nHost: 10.130.1.217\r\n\r\n" 10.130.1.217:80
Destination: [10.130.1.217]:80
Interface eth0 address [10.130.1.71]:0
Using interface eth0 to connect to [10.130.1.217]:80
Ramped up to 6000 connections.
Total data sent: 34716.8 MiB (36403218124 bytes)
Total data received: 1535.0 MiB (1609569208 bytes)
Bandwidth per channel: 0.479⇅ Mbps (59.9 kBps)
Aggregate bandwidth: 107.304↓, 2426.878↑ Mbps
Packet rate estimate: 15806.7↓, 207872.1↑ (2↓, 42↑ TCP MSS/op)
Test duration: 120 s.
nginx服务端观测到并发连接数如下:
可以看到在压测七层webserver时,压力端指定的并发连接数并不能达到,主要原因是有nginx服务端关闭连接造成。
Total: 8534 (kernel 8552)
TCP: 18313 (estab 816, closed 7288, orphaned 2809, synrecv 0, timewait 7288/0), ports 0
Transport Total IP IPv6
* 8552 - -
RAW 0 0 0
UDP 8 5 3
TCP 11025 11019 6
INET 11033 11024 9
FRAG 0 0 0
服务器端监听12345端口,接收到的包不做回应并丢弃:
#tcpkali -l 12345 -T 720
Every 1.0s: ss -s Sun Aug 11 16:11:55 2019
#检测到实际建立链接的并发量也就在6.4W左右
Total: 64178 (kernel 64311)
TCP: 63864 (estab 63839, closed 0, orphaned 2, synrecv 0, timewait 0/0), ports 0
Transport Total IP IPv6
* 64311 - -
RAW 0 0 0
UDP 8 5 3
TCP 63864 63854 10
INET 63872 63859 13
FRAG 0 0 0
客户端tcpkali虚机上有三张网卡,ip分别为10.130.1.71/24,10.130.1.11/24,10.130.1.110/24。使用–source-ip参数分别指定三张网卡来发起并发链接,每个连接每秒钟传输一个"PING"消息。发现客户端仍然只能建立6.4W个链接。使用-vvv打印详细的建立链接过程发现仍然是用三个网卡与对端建立链接的。但是链接超时。
# tcpkali --source-ip 10.130.1.71 --source-ip 10.130.1.11 --source-ip 10.130.1.110 --connections 180000 --connect-rate 100000 -m "PING" --message-rate 1 -T 120s 10.130.1.217:12345
WARNING: Will not be able to open 180000 simultaneous connections since "/proc/sys/net/ipv4/ip_local_port_range" specifies too narrow range [1025..65534].
Destination: [10.130.1.217]:12345
Source IP: [10.130.1.71]:0
Source IP: [10.130.1.11]:0
Source IP: [10.130.1.110]:0
|================>--------------------------------| 62437 of 180000 (358005)
Connection [10.130.1.11]:48233 -> [10.130.1.217]:12345 opened as 198
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection [10.130.1.11]:43493 -> [10.130.1.217]:12345 opened as 207
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection [10.130.1.71]:10702 -> [10.130.1.217]:12345 opened as 188
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection [10.130.1.110]:9942 -> [10.130.1.217]:12345 opened as 213
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection to [10.130.1.217]:12345 is being closed: Connection timed out
Connection [10.130.1.71]:53393 -> [10.130.1.217]:12345 opened as 216
这里笔者作死去压测百度的公网,然后居然能压测上…
tcpkali --source-ip 10.130.1.71 --source-ip 10.130.1.11 --source-ip 10.130.1.110 --connections 80000 --connect-rate 1000000 -T 120s www.baidu.com:80
WARNING: Will not be able to open 80000 simultaneous connections since "/proc/sys/net/ipv4/ip_local_port_range" specifies too narrow range [1025..65534].
Destination: [180.97.33.108]:80
Destination: [180.97.33.107]:80
Source IP: [10.130.1.71]:0
Source IP: [10.130.1.11]:0
Source IP: [10.130.1.110]:0
Ramped up to 80000 connections.
? Traffic 0.000↓, 0.000↑ Mbps (conns 0↓ 4015↑ 75985⇡; seen 2042906)
在本地使用tcpkali监听12345端口,压测127.0.0.1本地环回IP地址。
执行压测命令
# tcpkali --source-ip 10.130.1.71 --source-ip 10.130.1.11 --source-ip 10.130.1.110 --connections 180000 --connect-rate 1000000 -T 120s 127.0.0.1:12345
WARNING: Will not be able to open 180000 simultaneous connections since "/proc/sys/net/ipv4/ip_local_port_range" specifies too narrow range [1025..65534].
Destination: [127.0.0.1]:12345
Source IP: [10.130.1.71]:0
Source IP: [10.130.1.11]:0
Source IP: [10.130.1.110]:0
Ramped up to 180000 connections.
? Traffic 0.000↓, 0.000↑ Mbps (conns 0↓ 139753↑ 45446⇡; seen 843272)
执行监听端口命令并观察并发连接数
# tcpkali -l 12345 -T 720
Listen on: [0.0.0.0]:12345
Listen on: [::]:12345
? Traffic 0.000↓, 0.000↑ Mbps (conns 130903↓ 0↑ 0⇡; seen 112385088)
#watch -n 1 "ss -s"
Every 1.0s: ss -s Mon Aug 12 00:23:35 2019
Total: 300915 (kernel 304725)
TCP: 308814 (estab 278546, closed 6, orphaned 126, synrecv 0, timewait 6/0), ports 0
Transport Total IP IPv6
* 304725 - -
RAW 2 0 2
UDP 3 3 0
TCP 308808 308773 35
INET 308813 308776 37
FRAG 0 0 0