SIP测试-02-SIPp在语音系统压测中的使用方式

一提到语音系统压测, 第一个想到的工具就是 SIPp

这没有问题。
在 SIP / FreeSWITCH 场景里,SIPp 依然是非常实用的基础工具,尤其适合:

  • SIP 注册测试
  • 单路呼叫链路验证
  • 信令并发压测
  • 信令加媒体的基础模拟
  • 对 FreeSWITCH、SBC、网关等节点做容量摸底

SIPp 也很容易被误用。
最常见的误用方式大概有三类:

  • 把它当成“会发 INVITE 的工具”,脚本能跑就算完成
  • 单条命令打出高 CPS,就直接推整条语音链路容量
  • 一出问题就盯 XML 和参数,却不先拆注册、呼叫、路由和媒体阶段

所以这篇文章不打算写成安装教程,也不准备把所有命令参数过一遍。
更想讲的是:

在真实语音系统压测里,SIPp 应该怎么用,脚本该怎么拆,执行该怎么跑,问题该怎么查,结果才更可信。

一、SIPp 在语音压测里承担的角色,不只是“发包”

SIPp 第一次被拿来做语音压测时,很容易先被理解成“发起呼叫的工具”。
这只是表层。

在真实项目里,SIPp 更接近下面几种角色的组合:

  • SIP 终端模拟器
  • 注册与呼叫行为发生器
  • 并发压测流量发生器
  • 失败码采样器
  • 基础链路验证器

也就是说,SIPp 的价值不只是把报文发出去,而是帮你回答:

  • 在当前账号、路由和鉴权配置下,注册是否稳定
  • 在当前拨号计划下,呼叫能不能正确建立
  • 在并发拉高以后,失败码先从哪一类开始抬头
  • 当前问题更像脚本问题、配置问题,还是服务端瓶颈

如果只是把它当成“脚本工具”,你很容易停留在:

  • 命令能跑
  • 屏幕有数据
  • 结果却不一定能支撑判断

二、不建议一上来就做“全链路大压”,而是先拆 4 个层次

在语音系统里,最容易让压测失真的原因之一,就是把太多东西一次性绑在一起。

如果要组织,通常先拆成下面 4 层:

1. 注册层

先验证:

  • 账号能不能稳定注册
  • 401/407 挑战是否正常
  • 注册速率拉高以后服务器是否先出异常

2. 纯信令呼叫层

先验证:

  • INVITE -> 180/183 -> 200 -> ACK -> BYE 是否走通
  • 拨号计划和路由是否正确
  • 并发拉高以后失败码分布怎么变

3. 信令 + 媒体层

再验证:

  • 信令接通以后媒体是否真的建立
  • RTP 端口、编解码和媒体时长是否稳定
  • 是否出现单通、无声、早挂断

4. 信令 + 媒体 + 下游服务层

最后才验证:

  • FreeSWITCH 之外的语音服务、机器人服务、配置服务、识别服务是否一起承压
  • 哪一层最先拖慢整条链路

这套拆法的好处很直接:

  • 出问题时更容易定位是哪一层先跑偏
  • 每一层都能作为下一层的前置健康检查
  • 不会把所有问题都糊成“全链路不稳定”

三、更常用的脚本拆法:注册脚本、主叫脚本、被叫脚本分开

做语音压测时,更稳的做法通常不是只维护一个大 XML。
更可控的方式是拆成 3 类核心脚本。

1. 注册脚本

它的职责非常单纯:

  • REGISTER
  • 处理 401/407
  • 完成鉴权注册
  • 输出注册失败日志

注册脚本尽量不要混进呼叫逻辑。
这样你后面做注册压测时,失败原因会更干净。

2. 主叫脚本

主叫脚本通常负责:

  • INVITE
  • 处理临时响应和最终响应
  • 在接通后发 ACK
  • 根据时长或场景发 BYE

如果要打带鉴权的呼叫,主叫脚本里还要把认证挑战处理好。

3. 被叫脚本

被叫脚本更像一个行为响应器:

  • 接收 INVITE
  • 返回 180/183/200
  • 维持通话
  • 接收或发送 BYE

这样拆开的最大好处是,压测执行时你能清楚知道:

  • 现在问题是在注册层
  • 还是主叫发起层
  • 还是被叫响应层

四、更适合的一种目录结构

为了避免语音压测脚本越来越乱,通常会把目录收成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sipp-project/
├── scenario/
│ ├── register_client.xml
│ ├── caller_auth.xml
│ ├── callee_answer.xml
│ └── ooc_default.xml
├── data/
│ ├── uac.csv
│ ├── uas.csv
│ └── auth.csv
├── pcap/
│ ├── g711a.pcap
│ └── g711u.pcap
├── logs/
└── README.md

这套结构不复杂,但特别实用:

  • scenario/ 放场景脚本
  • data/ 放账号和鉴权数据
  • pcap/ 放媒体文件
  • logs/ 放执行结果

后面排障时,你至少不会先花时间找文件。

五、正式执行前,先做一轮最小验证

SIPp 压测里最容易犯的错误,就是还没验证最小链路,就直接拉高 CPS。
这样一旦失败,很难判断是工具、脚本还是系统问题。

通常会先做下面几步:

  1. 单账号注册验证
  2. 单主叫 + 单被叫呼叫验证
  3. 带日志跑一轮最小通话
  4. 再逐步拉高并发和媒体复杂度

一个很常见的最小执行顺序是:

1
2
3
4
5
6
7
8
9
10
11
# 1. 启动主叫注册
sipp -sf scenario/register_client.xml 192.168.200.101:5060 -i 192.168.200.101 -p 26045 -inf data/uac.csv -m 10 -trace_err

# 2. 启动被叫注册
sipp -sf scenario/register_client.xml 192.168.200.101:5060 -i 192.168.200.101 -p 26048 -inf data/uas.csv -m 10 -trace_err

# 3. 启动被叫监听
sipp -sf scenario/callee_answer.xml -i 192.168.200.101 -p 26048 -trace_err

# 4. 启动主叫呼叫
sipp -sf scenario/caller_auth.xml 192.168.200.101:5060 -i 192.168.200.101 -p 26045 -inf data/uac.csv -m 10 -d 10000 -trace_msg -trace_err

这一步的目标不是压系统,而是确认:

  • 注册正常
  • 呼叫链路正常
  • 鉴权正常
  • 被叫响应正常
  • 脚本里的字段替换和号码映射没有跑偏

六、真正进入压测时,更关注 CPS、并发和通话时长的关系

语音压测里最容易误读的一个点是:

  • -r 很大
  • 所以系统很强

这个结论通常不成立。

因为电话场景不是纯请求响应模型。
它更像:

  • 不断发起呼叫
  • 呼叫建立后还要占住资源一段时间

所以我现场更关注的是:

  • CPS:每秒发起多少呼叫
  • CC:同时在线通话数
  • 通话时长:一通电话要占多久

一个很实用的近似理解是:

1
并发通话数(CC) ≈ CPS × 平均通话时长

这意味着:

  • 同样是 100 CPS
  • 如果通话时长是 5 秒,并发占用和 60 秒 完全不是一个量级

所以跑 SIPp 时,不能只盯 -r,还要把 -d-l-m 一起看。

七、更常用的一套执行节奏

如果要正式做一轮信令压测,更稳的方式通常是按阶段跑,而不是一步到顶。

例如:

阶段 目标 典型参数 观察重点
阶段 1 单链路验证 -m 10 报文流程是否完整
阶段 2 小并发摸底 -r 10 -l 50 鉴权、路由、失败码
阶段 3 中并发观察 -r 50 -l 500 FreeSWITCH 会话数、失败码分布
阶段 4 目标压测 -r 100+ CPS、CC、错误比例、日志异常

每个阶段结束后,通常会记录 4 类信息:

  • 执行参数
  • 失败码分布
  • FreeSWITCH 或服务端资源状态
  • 当前判断是脚本问题、配置问题还是服务端瓶颈

这样后面写报告时,不会只剩一堆 trace_err 文件。

八、SIPp 压测里最常见的几个误区

1. 注册都成功了,就默认呼叫也应该成功

这是非常常见的误判。
注册成功只能说明账号和基础鉴权没问题,不代表:

  • 拨号计划正确
  • 路由正确
  • 被叫在线
  • 外部网关可达

2. 失败码一多,就先怀疑脚本

脚本当然可能有问题,但如果失败码是成批出现,而且带明显模式,很多时候更该先看:

  • 路由
  • 服务器会话数
  • 鉴权配置
  • 白名单和 ACL

3. 纯信令结果直接推全链路容量

这也很危险。
纯信令压测通常只能回答:

  • SIP 服务器这层的大致承压能力

但它不能直接回答:

  • 加上媒体后还能不能稳定
  • 加上机器人、识别、配置服务后还能不能稳定

九、真实案例型段落:一次“脚本能跑,但压测结论完全不可信”的修正

场景

一次 FreeSWITCH 压测前,团队已经写好了主叫和被叫脚本。
第一轮执行时,屏幕上数据跑得很热闹,看起来:

  • CPS 也起来了
  • 失败率也不算高
  • 所以现场最开始很容易判断脚本已经可以进正式压测

执行

当时的执行方式比较直接:

  1. 注册脚本跑一轮
  2. 被叫脚本启动
  3. 主叫脚本直接用较高的 -r-l 开始打

日志参数没有完全收敛,媒体也已经一起带上了。

现象

现场很快出现几个问题:

  • 部分呼叫是 480
  • 部分呼叫是 407
  • 少量呼叫虽然接通,但挂断节奏不稳定
  • 不同轮次结果波动比较大

更麻烦的是,因为注册、呼叫、媒体一起上了,团队没法快速回答:

  • 到底是认证挑战没处理好
  • 还是被叫没准备好
  • 还是媒体播放拖慢了本地执行

排查

我当时更倾向先把问题拆开,而不是继续加日志硬查:

  1. 先把媒体播放去掉,只保留纯信令
  2. 把主叫并发降下来,只保留最小链路
  3. 单独看 407 是正常挑战还是异常失败
  4. 再看被叫脚本是否真的在预期端口和时机进入监听

拆开以后发现,真正的问题不是系统先扛不住,而是:

  • 主叫呼叫脚本里鉴权挑战处理并不稳定
  • 被叫监听启动时机和主叫压测启动时机没有完全对齐
  • 一上来就带媒体,让本来已经模糊的问题更难解释

修复

修复动作分成 3 步:

  1. 先把注册、纯信令、媒体三层拆开执行
  2. 先用最小链路把 407 -> ACK -> 再次 INVITE 的认证流程跑稳
  3. 等纯信令稳定后,再单独加回媒体播放

修复后,压测节奏变得清楚很多:

  • 第一轮只看注册
  • 第二轮只看呼叫建立
  • 第三轮才看媒体和更高并发

这个案例最直接的提醒是:

SIPp 的问题经常不在“工具会不会用”,而在“你有没有把压测对象拆对”。

十、更常用的一套排查顺序

如果现场出现大量失败,可以按下面顺序排:

  1. 先看失败发生在注册还是呼叫阶段
  2. 再看高频失败码是哪一类
  3. 再看服务器侧是会话、鉴权、路由还是 ACL 先异常
  4. 如果 200 OK 都没稳定出现,先别急着查媒体
  5. 只有在纯信令稳定后,才值得继续查 RTP 和音频问题

这套顺序最大的价值,是能尽量避免:

  • 还没跑通基本链路就开始查复杂问题
  • 明明是前置配置错误,却被解释成系统性能瓶颈

结语

SIPp 在语音系统压测里真正重要的,不是 XML 写得多复杂,而是你能不能把它组织成一套可信的压测方法:

  • 先拆层
  • 再拆脚本
  • 再做最小链路验证
  • 最后才逐步上并发、上媒体、上全链路

只要这个顺序对了,SIPp 才不会只是一个“会发 SIP 报文的工具”,而会变成你做语音系统压测和排障的基础能力。