概述
SIP压测工具sipp,免费,开源,功能足够强大,配置灵活,优点多。
有时候我们需要模拟现网的生产环境来压测,就需要同时有多个sipp脚本运行,并且需要不断的调整呼叫并发。
通过python脚本的子进程功能,我们可以很方便的实现sipp的多方案压测功能。
环境
centos7.9
freeswitch1.10.7
sipp v3.6.2_rc1
python 2.7.5
压测方案
Freeswitch部署在137服务器,作为呼叫的信令代理,开放端口5080。
Sipp和python脚本部署在138服务器,sipp的测试方案需要启动4个进程。
Sipp1,uas端,开启5555端口,接收fs137转发的呼叫,并响应接通信令。
Sipp2,uac端,开启6666端口,向fs137发送呼叫,并在接通30秒后挂断电话。
Sipp3,uac端,开启7777端口,向fs137发送呼叫,并接收fs137返回的404信令但不处理。
Sipp4,uac端,开启6668端口,向fs137发送呼叫,并在收到180振铃消息后主动cancel呼叫。
其中,sipp2,sipp3,sipp4三个uac端的进程,每间隔3分钟发起新一轮呼叫,每一轮呼叫运行2分钟。
Sipp1配置脚本
Sipp1,uas端,开启5555端口,接收fs137转发的呼叫,并响应接通信令。
监听10.55.55.138的5555端口,命令和脚本如下。
sudo sipp -i 10.55.55.138 -p 5555 -sf uas-test180cps.xml
uas-test180cps.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="Basic UAS responder">
<recv request="INVITE" crlf="true">
</recv>
<send>
<![CDATA[
SIP/2.0 100 Trying
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag08b[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>
<pause milliseconds="500"/>
<send>
<![CDATA[
SIP/2.0 180 Ringing
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Type: application/sdp
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 8
a=rtpmap:8 PCMA/8000
a=ptime:20
]]>
</send>
<pause milliseconds="500"/>
<send>
<![CDATA[
SIP/2.0 180 Ringing
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>
<pause milliseconds="500"/>
<send retrans="500">
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Type: application/sdp
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 8
a=rtpmap:8 PCMA/8000
]]>
</send>
<recv request="ACK"
optional="true"
rtd="true"
crlf="true">
</recv>
<recv request="BYE">
</recv>
<send>
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_From:]
[last_To:]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>
<!-- Keep the call open for a while in case the 200 is lost to be -->
<!-- able to retransmit it if we receive the BYE again. -->
<timewait milliseconds="4000"/>
<!-- definition of the response time repartition table (unit is ms) -->
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
<!-- definition of the call length repartition table (unit is ms) -->
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
</scenario>
Sipp2配置脚本
Sipp2,uac端,开启6666端口,向fs137发送呼叫,并在接通30秒后挂断电话。
使用10.55.55.138的6666端口向10.55.55.137的5080端口发起呼叫,每秒发起160通呼叫,总共发起19200通呼叫后停止运行,后台运行。
sudo sipp -i 10.55.55.138 -p 6666 -inf call-test.csv -sf uac-test180cps.xml 10.55.55.137:5080 -rp 1000 -r 160 -l 8192 -m 19200 -bg
uac-test180cps.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="Basic Sipstone UAC">
<send retrans="500">
<![CDATA[
INVITE sip:[field1]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tgrp=TG-19073;tag=[pid]SIPpTag00[call_number]
To: [field1] <sip:[field1]@[remote_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: 1 INVITE
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: Performance Test
Content-Type: application/sdp
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 8 18
a=rtpmap:8 PCMA/8000
a=rtpmap:18 G729/8000
a=ptime:20
]]>
</send>
<recv response="100" optional="true">
</recv>
<recv response="183" optional="true">
</recv>
<recv response="180" optional="true">
</recv>
<recv response="200" rtd="true">
</recv>
<send>
<![CDATA[
ACK sip:[field1]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
To: [field1] <sip:[field1]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
CSeq: 1 ACK
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: Performance Test
Content-Length: 0
]]>
</send>
<pause milliseconds="30000"/>
<send retrans="500">
<![CDATA[
BYE sip:[field1]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
To: [field1] <sip:[field1]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
CSeq: 2 BYE
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: Performance Test
Content-Length: 0
]]>
</send>
<recv response="200" crlf="true">
</recv>
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
</scenario>
Sipp3配置脚本
Sipp3,uac端,开启7777端口,向fs137发送呼叫,并接收fs137返回的404信令但不处理。
使用10.55.55.138的7777端口向10.55.55.137的5080端口发起呼叫,每秒发起30通呼叫,总共发起3600通呼叫后停止运行,后台运行。
sudo sipp -i 10.55.55.138 -p 7777 -inf call-test.csv -sf uac-test404-noack.xml 10.55.55.137:5080 -rp 1000 -r 30 -l 8192 -m 3600 -bg
uac-test404-noack.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="Basic Sipstone UAC">
<send retrans="500">
<![CDATA[
INVITE sip:[field1]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
To: [field1] <sip:[field1]@[remote_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: 1 INVITE
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: Performance Test
Content-Type: application/sdp
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 8 18
a=rtpmap:8 PCMA/8000
a=rtpmap:18 G729/8000
a=ptime:20
]]>
</send>
<recv response="100" optional="true">
</recv>
<recv response="183" optional="true">
</recv>
<recv response="180" optional="true">
</recv>
<recv response="404" rtd="true">
</recv>
<timewait milliseconds="1000"/>
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
</scenario>
Sipp4配置脚本
Sipp4,uac端,开启6668端口,向fs137发送呼叫,并在收到180振铃消息后主动cancel呼叫。
使用10.55.55.138的6668端口向10.55.55.137的5080端口发起呼叫,每秒发起10通呼叫,总共发起1200通呼叫后停止运行,后台运行。
sudo sipp -i 10.55.55.138 -p 6668 -inf call-test.csv -sf uac-test-cancel1.xml 10.55.55.137:5080 -rp 1000 -r 10 -l 8192 -m 1200 -bg
uac-test-cancel1.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="Basic Sipstone UAC">
<send retrans="500">
<![CDATA[
INVITE sip:[field1]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
To: [field1] <sip:[field1]@[remote_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: 1 INVITE
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: Performance Test
Content-Type: application/sdp
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 8 18
a=rtpmap:8 PCMA/8000
a=rtpmap:18 G729/8000
a=ptime:20
]]>
</send>
<recv response="100" rtd="true">
</recv>
<recv response="180" >
</recv>
<recv response="180" >
</recv>
<pause milliseconds="200"/>
<send retrans="500">
<![CDATA[
CANCEL sip:[field1]@[remote_ip]:[remote_port] SIP/2.0
[last_Via:]
From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
To: [field1] <sip:[field1]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
CSeq: 1 CANCEL
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Content-Length: 0
]]>
</send>
<recv response="200" crlf="true">
</recv>
<recv response="487" crlf="true">
</recv>
<send>
<![CDATA[
ACK sip:[field1]@[remote_ip]:[remote_port] SIP/2.0
[last_Via:]
From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
To: [field1] <sip:[field1]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
CSeq: 1 ACK
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: Performance Test
Content-Length: 0
]]>
</send>
<timewait milliseconds="1000"/>
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
</scenario>
Python脚本
该Python脚本可以在python2和python3的环境下运行,测试环境只跑了python2。
脚本如下,通过subprocess子进程实现压测方案的自动启停。
sipp-auto.py
# coding=utf-8
# python3 required
import subprocess
import time
import signal
import sys
def signal_handler(sig, frame):
continueflag = 0
for p in processes:
p.terminate()
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
commands = [
# "sudo sipp -i 10.55.55.138 -p 5555 -sf uas-test180cps.xml",
"sudo sipp -i 10.55.55.138 -p 6666 -inf call-test.csv -sf uac-test180cps.xml 10.55.55.137:5080 -rp 1000 -r 160 -l 8192 -m 19200 -bg",
"sudo sipp -i 10.55.55.138 -p 7777 -inf call-test.csv -sf uac-test404-noack.xml 10.55.55.137:5080 -rp 1000 -r 30 -l 8192 -m 3600 -bg",
"sudo sipp -i 10.55.55.138 -p 6668 -inf call-test.csv -sf uac-test-cancel1.xml 10.55.55.137:5080 -rp 1000 -r 10 -l 8192 -m 1200 -bg"
]
continueflag = 1
processes = []
commandUas = "sudo sipp -i 10.55.55.138 -p 5555 -sf uas-test180cps.xml"
p = subprocess.Popen(commandUas, shell=True)
processes.append(p)
while 1==continueflag:
for command in commands:
p = subprocess.Popen(command, shell=True)
processes.append(p)
time.sleep(180) # 等待3分钟
for p in processes:
p.wait()
测试
Sipp的配置脚本和python脚本放置到相同目录下。
启动python脚本。
sudo python sipp-auto.py
观察fs资源情况和sipp运行情况。
总结
sipp的github地址:https://github.com/SIPp/sipp
后续会有更多的压测方案和脚本慢慢写。
空空如常
求真得真