FreeSWITCH通话记录接口:CDR模块设计与优化实践
一、CDR模块基础架构解析
通话记录(Call Detail Record, CDR)是VoIP系统的核心组件,用于记录每次通话的元数据,包括主被叫号码、通话时长、计费信息等。在FreeSWITCH中,CDR模块通过事件订阅机制捕获通话生命周期事件,并将其转换为结构化数据。
1.1 事件驱动架构
FreeSWITCH采用事件驱动模型,CDR生成依赖以下关键事件:
CHANNEL_CREATE:通话建立时触发CHANNEL_ANSWER:被叫应答时触发CHANNEL_DESTROY:通话结束时触发DTMF:按键事件(可选记录)
模块通过mod_event_socket或内置mod_cdr监听这些事件,将原始事件数据映射为CDR字段。例如:
<!-- FreeSWITCH配置示例:启用CDR模块 --><configuration name="cdr.conf" description="CDR Configuration"><settings><param name="csv-dir" value="/var/log/freeswitch/cdr"/><param name="csv-format" value="csv"/><param name="pg-csv" value="true"/> <!-- 启用PostgreSQL存储 --></settings></configuration>
1.2 核心数据结构
CDR字段通常包含以下维度:
| 字段名 | 类型 | 描述 |
|————————|——————|—————————————|
| uuid | STRING | 通话唯一标识符 |
| caller_id | STRING | 主叫号码 |
| destination | STRING | 被叫号码 |
| start_epoch | INTEGER | 通话开始时间(Unix时间戳)|
| answer_epoch | INTEGER | 被叫应答时间 |
| end_epoch | INTEGER | 通话结束时间 |
| duration | INTEGER | 通话总时长(秒) |
| billsec | INTEGER | 计费时长(秒) |
| hangup_cause | STRING | 挂断原因 |
二、CDR接口实现方案
FreeSWITCH支持多种CDR输出方式,开发者可根据业务需求选择适配方案。
2.1 本地文件存储
方案特点:简单易用,适合小型系统
实现步骤:
- 修改
cdr.conf配置CSV输出路径 - 设置定时任务归档日志文件
- 通过脚本解析CSV进行二次处理
示例代码(Python解析CSV):
import csvfrom datetime import datetimedef parse_cdr(file_path):with open(file_path, 'r') as f:reader = csv.DictReader(f)for row in reader:start_time = datetime.fromtimestamp(int(row['start_epoch']))duration = int(row['duration'])print(f"通话时间: {start_time}, 时长: {duration}秒")
2.2 数据库集成
方案特点:实时性强,支持复杂查询
主流数据库适配:
- PostgreSQL:通过
mod_db模块直接写入<param name="db-url" value="postgres://user:pass@localhost/cdrdb"/>
- MySQL:需配置ODBC驱动
- 时序数据库:适合大规模CDR分析(如InfluxDB)
性能优化建议:
- 批量插入替代单条提交
- 为
uuid和start_epoch建立复合索引 - 分表策略(按日期或客户ID)
2.3 消息队列中转
适用场景:高并发、解耦存储与处理
实现流程:
- 配置
mod_erlang_event或mod_kafka - 定义消息格式(JSON/Protobuf)
- 消费者服务处理CDR数据
Kafka生产者配置示例:
<configuration name="kafka.conf"><producers><producer name="cdr_producer"><param name="brokers" value="kafka1:9092,kafka2:9092"/><param name="topic" value="freeswitch_cdr"/></producer></producers></configuration>
三、高级功能实现
3.1 自定义字段扩展
通过cdr_custom变量注入业务数据:
<action application="set" data="cdr_custom=${call_type}_${campaign_id}"/>
在cdr.conf中映射:
<param name="custom-fields" value="call_type,campaign_id"/>
3.2 实时计费引擎
结合Lua脚本实现动态费率计算:
session:setVariable("billsec", duration)local rate = 0.02 -- 每秒费率local cost = rate * durationsession:execute("set", "cdr_cost=" .. cost)
3.3 多租户隔离
通过domain变量实现租户级CDR分离:
<param name="csv-filename" value="${domain}_cdr_${strftime(%Y%m%d)}.csv"/>
四、性能优化与故障排查
4.1 瓶颈分析与调优
常见问题:
- 高并发写入延迟:数据库连接池不足
- 磁盘I/O过载:CSV文件未做轮转
- 内存泄漏:未释放的CDR事件句柄
优化方案:
- 启用异步写入模式
- 增加
mod_cdr的buffer-size参数 - 对历史CDR实施冷热数据分离
4.2 监控指标
关键监控项:
| 指标名 | 阈值 | 告警策略 |
|—————————|——————|————————————|
| CDR生成延迟 | <500ms | 超过1s触发告警 |
| 数据库写入TPS | >200/秒 | 下降50%时告警 |
| 磁盘空间使用率 | <85% | 超过90%自动清理旧数据 |
五、安全与合规实践
5.1 数据脱敏处理
通话记录涉及用户隐私,需实施:
- 主被叫号码部分隐藏(如
138****1234) - 录音文件加密存储
- 访问权限分级控制
5.2 合规性要求
- 符合GDPR、等保2.0等法规
- 保留CDR数据不少于6个月
- 提供用户数据查询/删除接口
六、部署架构建议
6.1 单机部署方案
适用场景:中小型呼叫中心
架构图:
FreeSWITCH → mod_cdr(CSV) → Logrotate → 分析服务
6.2 分布式集群方案
适用场景:大型云呼叫中心
架构组件:
- Zookeeper:协调多节点CDR收集
- Kafka集群:缓冲高并发CDR
- Flink流处理:实时计算KPI
- ClickHouse:OLAP分析
七、未来演进方向
- AI驱动分析:通过CDR数据训练通话质量预测模型
- 区块链存证:确保CDR不可篡改性
- 边缘计算:在网关侧预处理CDR减少核心网压力
通过系统化的CDR接口设计,企业可构建从基础通话记录到智能运营分析的完整闭环。实际部署时,建议结合业务规模选择渐进式技术演进路径,初期优先保障数据完整性与系统稳定性,再逐步叠加高级分析功能。