SipFlow 集群部署

SipFlow 是 RustPBX 内置的 SIP+RTP 信令抓包和回放系统,支持本地模式和独立集群模式。

1. 功能概述

能力说明
SIP 信令抓包完整的 SIP 请求/响应报文
RTP 媒体抓包可选,按录音策略触发
WAV 回放从 RTP 包生成通话录音
时间线浏览Web 控制台中按 call_id 查看完整信令流
S3/HTTP 上传通话结束后上传到对象存储

2. 本地模式(单节点)

2.1 配置

[sipflow]
[sipflow.local]
subdirs = "daily"          # none / daily / hourly
flush_count = 100          # 每 100 包刷新到磁盘
flush_interval_secs = 5    # 最长 5 秒刷新
id_cache_size = 10000      # Call-ID 缓存大小

2.2 存储结构

sipflow/
├── 20260526/
│   ├── 20260526.sqlite     # 元数据索引
│   └── 20260526.raw        # 原始报文(zstd 压缩)
├── 20260527/
│   ├── 20260527.sqlite
│   └── 20260527.raw
  • *.sqlite:每条记录包含 call_id、时间戳、源/目的 IP/端口、SIP 方法
  • *.raw:二进制报文数据,zstd 压缩

2.3 RTP 录音生成

从抓包数据生成 WAV:

GET /api/sipflow/media?call_id=xxx&start=0&end=3600&format=wav

支持 PCMU、PCMA、G722、L16 编解码转 WAV。

2.4 上传配置

通话结束后自动上传:

[sipflow.upload]
type = "s3"
bucket = "sipflow-archives"
region = "us-east-1"
endpoint = "https://s3.amazonaws.com"
access_key = "AKIA..."
secret_key = "secret..."

# 或上传到 HTTP
# [sipflow.upload]
# type = "http"
# url = "https://api.example.com/sipflow/upload"

3. 独立集群模式

多节点部署时,SipFlow 可部署为独立服务,通过一致性哈希路由。

3.1 架构

┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│  RustPBX    │  │  RustPBX    │  │  RustPBX    │
│  Node 1     │  │  Node 2     │  │  Node 3     │
└──────┬──────┘  └──────┬──────┘  └──────┬──────┘
       │                │                │
       │   UDP 报文 + HTTP 查询           │
       ▼                ▼                ▼
┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│  SipFlow    │  │  SipFlow    │  │  SipFlow    │
│  Server A   │  │  Server B   │  │  Server C   │
│  :3000/3001 │  │  :3000/3001 │  │  :3000/3001 │
└─────────────┘  └─────────────┘  └─────────────┘
  • RustPBX 节点通过 call_id 一致性哈希选择 SipFlow Server
  • 每个 SipFlow Server 独立存储
  • 查询时自动路由到正确的 Server

3.2 SipFlow Server 部署

SipFlow Server 是独立的二进制(sipflow),从 RustPBX 源码编译:

cargo build --release --bin sipflow

启动参数:

/static/docs-zh/addons/sipflow \
  --addr 0.0.0.0 \
  --port 3000 \           # UDP 接收端口
  --http-port 3001 \      # HTTP API 端口
  --root /data/sipflow \  # 存储目录
  --flush-count 200 \     # 刷新包数
  --flush-interval 5 \    # 刷新间隔秒
  --buffer-size 65536     # UDP 接收缓冲区

Docker 部署:

docker run -d --name sipflow-a \
  -v /data/sipflow:/data/sipflow \
  -p 3000:3000/udp -p 3001:3001 \
  docker.cnb.cool/miuda.ai/rustpbx:latest \
  /app/sipflow --addr 0.0.0.0 --port 3000 --http-port 3001 --root /data/sipflow

3.3 SipFlow Server HTTP API

端点方法说明
/healthGET健康检查
/flowGET查询 SIP 信令(callid, start, end 参数)
/mediaGET生成 WAV 录音(callid, start, end, format 参数)

3.4 RustPBX 节点配置

每个 RustPBX 节点配置 SipFlow 远程后端:

[sipflow]
[sipflow.remote]
flush_interval_secs = 5

[[sipflow.remote.nodes]]
udp = "10.0.1.1:3000"
http = "http://10.0.1.1:3001"

[[sipflow.remote.nodes]]
udp = "10.0.1.2:3000"
http = "http://10.0.1.2:3001"

[[sipflow.remote.nodes]]
udp = "10.0.1.3:3000"
http = "http://10.0.1.3:3001"

路由规则:

  • 写入:hash(call_id) % node_count → 选择目标 Server,UDP 发送
  • 查询:同样哈希路由到正确的 Server,HTTP GET 请求

3.5 一致性哈希

SipFlow 使用简单取模哈希(非一致性哈希环):

  • 增减节点时,约 1/N 的 call_id 会路由变化
  • 建议在规划时确定节点数,避免频繁变更
  • 节点变更后,历史数据的查询可能需要逐节点遍历

4. Web 控制台查看

控制台 → 通话记录 → 点击通话 → SIP Flow:

在 CDR 列表中点击任意通话,查看完整的 SIP 信令时间线:

  • 每条 SIP 消息的时序
  • 请求/响应配对
  • RTP 流信息
  • 可播放通话录音

5. 存储规划

5.1 磁盘空间估算

数据类型每通电话大小1 万通/天/月
SIP 信令~5 KB~150 MB
RTP 媒体(可选)~50-200 KB~1.5-6 GB
SQLite 索引~500 B~15 MB

5.2 保留策略

建议通过定时任务清理过期数据:

# 删除 90 天前的数据
find /data/sipflow -maxdepth 1 -type d -name "20*" -mtime +90 -exec rm -rf {} \;

或配置上传到 S3 后本地自动清理。

6. 网络要求

端口协议用途
3000UDPRustPBX → SipFlow 报文传输
3001HTTPRustPBX → SipFlow 查询 API

RustPBX 节点需要能访问所有 SipFlow Server 的 UDP 和 HTTP 端口。

7. 录音策略与 SipFlow 的关系

SipFlow 抓包与通话录音是独立的:

配置说明
[recording]通话录音(WAV/MP3)
[sipflow]信令抓包(SIP+RTP 包)
  • SipFlow RTP 抓包跟随录音策略(仅录音的通话才抓 RTP)
  • SIP 信令始终抓取(无论是否录音)
  • SipFlow 生成的 WAV 可作为录音备份