Yeti-Switch 配置参数详解
Yeti-Switch 三层配置全解:SEMS + yeti module 流量平面 sems.conf(general/signaling/media/modules/yeti/jsonrpc/redis)、yeti-web Rails 管理平面(database.yml/yeti_web.yml/secrets.yml)、PostgreSQL 18 双库与 Redis 生产模板(PoC/中型/集群三档)。
Yeti-Switch 配置参数详解
目标:完整覆盖 Yeti-Switch v1.14 的三层配置体系——SEMS + yeti module 流量平面(/etc/sems/sems.conf)、yeti-web Rails 管理平面(/opt/yeti-web/config/*.yml)、PostgreSQL 双库与 Redis 基础设施配置。所有参数来自官方 1.14 安装指南与 SEMS 配置参考,按功能域分组,含类型/默认值/说明/生产推荐。检索日期 2026-10-27。
一、环境信息
- Yeti-Switch 版本:1.14.x(1.15.x 参数基本兼容,新增 OAuth/OIDC 配置项见 changelog)
- 依赖:SEMS(yeti 维护分支)、PostgreSQL 18 + 扩展、Redis 7.x、yeti-web (Rails 7.2)
- 配置文件位置(裸机):
- SEMS:
/etc/sems/sems.conf - yeti-web 数据库:
/opt/yeti-web/config/database.yml - yeti-web 安全密钥:
/opt/yeti-web/config/secrets.yml - yeti-web 业务参数:
/opt/yeti-web/config/yeti_web.yml - Redis:
/etc/redis/redis.conf - PostgreSQL:
/etc/postgresql/18/main/postgresql.conf+pg_hba.conf - systemd:
/lib/systemd/system/sems.service+/lib/systemd/system/yeti-*.service
- SEMS:
二、前置条件
2.1 参数查看方式
| 平面 | 查看方式 |
|---|---|
| SEMS | 直接 cat 配置文件;运行态参数 yeti-cli 查看(yeti-cli sems.show.*) |
| yeti-web | 配置文件;Rails Console 动态查看(rails runner 'puts YetiConfig.to_h') |
| PostgreSQL | SHOW ALL; |
| Redis | redis-cli CONFIG GET * |
2.2 参数修改生效范围
| 组件 | 配置修改 | 生效方式 |
|---|---|---|
| SEMS(流量平面) | /etc/sems/sems.conf 多数 | systemctl restart sems |
| SEMS yeti 实体缓存 | 网关/路由/账号 | Web UI 保存后 yeti 模块 JSONRPC 热重载(5s 内) |
| yeti-web | database.yml / secrets.yml / yeti_web.yml | systemctl restart yeti-web |
| Redis | /etc/redis/redis.conf | systemctl restart redis-server |
| PostgreSQL | postgresql.conf | systemctl restart postgresql@18-main |
| pgqd | /etc/pgqd.ini | service pgqd restart |
💡 技术拓展:Yeti-Switch 的「流量平面热重载」——SEMS yeti 模块把网关、路由、账号、费率、认证凭据等实体缓存在内存。yet-web 的保存动作会通过 PostgreSQL LIST/NOTIFY 或 JSONRPC 触发 SEMS 重拉对应表。这是 Yeti 相对 FreeSWITCH dialplan 的核心优势之一:路由/计费规则改完秒级生效,无需重启流量进程。
三、参数总览
三层配置结构:
Yeti-Switch 配置
├── SEMS + yeti module(/etc/sems/sems.conf)—— 流量平面
│ ├── general {} —— 进程级参数
│ ├── signaling-interfaces {} —— SIP 信令监听
│ ├── media-interfaces {} —— RTP 媒体监听
│ └── modules {} —— 各功能模块(yeti/jsonrpc/redis/postgresql/...)
├── yeti-web(/opt/yeti-web/config/*.yml)—— 管理平面
│ ├── database.yml —— PostgreSQL 双库连接
│ ├── secrets.yml —— Rails secret_key_base
│ ├── yeti_web.yml —— 业务参数(OAuth、CDR、PDF、S3 等)
│ └── nginx.conf —— Nginx 反代 yeti-web.dist.nginx
├── Redis(/etc/redis/redis.conf)
├── PostgreSQL 18(routing + cdr 双库独立配置)
└── pgqd(CDR ticker)
四、SEMS + yeti module 核心参数详解
4.1 general {} —— 进程级
| 参数 | 类型 | 默认 | 说明 | 生产推荐 |
|---|---|---|---|---|
stderr | bool | yes | 输出到 stderr | no(改 syslog) |
syslog_loglevel | int | 2 | syslog 日志级别(0=fatal…5=debug) | 2 或 3(线上不低于 2,排障临时升 5) |
syslog_facility | enum | LOCAL0 | syslog facility | LOCAL0 或 LOG_DAEMON |
node_id | int | — | 本 SEMS Node ID(yet-web System→Nodes 创建后填写) | 必填,集群每节点唯一 |
media_processor_threads | int | 2 | 媒体转码线程数 | = CPU 核数(8 vCPU 配 8) |
rtp_receiver_threads | int | 1 | RTP 接收线程 | = CPU 核数 |
session_processor_threads | int | 10 | 会话处理线程(决定并发上限) | = 20–50(视并发,电信级 ≥ 40) |
sip_udp_server_threads | int | 1 | SIP UDP 监听线程 | 2 |
sip_tcp_server_threads | int | 1 | SIP TCP 监听线程 | 2 |
dead_rtp_time | int (sec) | 30 | RTP 静默超时自动断呼 | 30(短一点防僵尸) |
default_bl_ttl | int (sec) | 0 | 黑名单/容量计数器默认 TTL | 0(永久,靠 yeti-web 管理) |
symmetric_rtp_mode | enum | packets | NAT 穿透 symmetric RTP 模式:packets/auto/off | packets(最保守) |
symmetric_rtp_packets | int | 10 | symmetric RTP 判定包数 | 20(更保守) |
生产模板片段:
general {
stderr = no
syslog_loglevel = 2
syslog_facility = LOCAL0
node_id = 1
media_processor_threads = 8
rtp_receiver_threads = 8
session_processor_threads = 40
sip_udp_server_threads = 2
sip_tcp_server_threads = 2
dead_rtp_time = 30
symmetric_rtp_mode = packets
symmetric_rtp_packets = 20
}
4.2 signaling-interfaces {} —— SIP 信令
signaling-interfaces {
interface <NAME> {
default-media-interface = <MEDIA_IFACE_NAME>
ip4 {
sip-udp {
address = <0.0.0.0 或 具体 IP>
port = 5060
use-raw-sockets = off # on = 高性能原始套接字(可能需 CAP_NET_RAW)
}
sip-tcp {
address = <IP> port = 5060
connect-timeout = 2000
static-client-port = on # 固定 TCP 源端口
idle-timeout = 900000 # 15 分钟
}
}
# IPv6 类似:ip6 { sip-udp {...} sip-tcp {...} }
}
}
生产关键:
address填具体公网 IP(NAT 场景),0.0.0.0是通配但对端看到的 Via 会是 0.0.0.0;use-raw-sockets = on在万级 CPS 场景下降低 UDP recvfrom 开销,需 SEMS 进程CAP_NET_RAW或 root;- TLS 端口(5061)在 Sip-TLS 节单独配置证书路径。
4.3 media-interfaces {} —— RTP 媒体
media-interfaces {
interface <NAME> {
ip4 {
rtp {
address = <MEDIA_IP>
low-port = 16384
high-port = 32769
dscp = 46 # EF Expedited Forwarding
use-raw-sockets = off
}
}
}
}
生产关键:
- RTP 端口范围
low-port~high-port决定可并发通话数:(high - low) / 2 ≈ 单节点并发上限;16384–32769 约 8000 并发; dscp = 46给媒体流 EF 优先级,交换机/QoS 配置对应队列;- 端口范围不可与宿主机其他媒体服务重叠(FreeSWITCH 默认 16384–32768,正好同范围!)。
4.4 modules.module "yeti" {} —— 核心 yeti 模块
这是 Yeti-Switch 的心脏,子参数按功能域分组:
4.4.1 基础
| 参数 | 类型 | 默认 | 说明 | 生产推荐 |
|---|---|---|---|---|
pop_id | int | — | PoP ID(yet-web 创建后填) | 必填 |
auth.realm | string | yeti-switch | SIP Digest 鉴权 realm | yeti-switch 或自定义 |
msg_logger_dir | path | /var/spool/sems/dump | Pcap dump 目录 | /var/spool/sems/dump,定期清理 |
audio_recorder_dir | path | /var/spool/sems/records | 录音目录(若启用) | 独立盘挂载 |
audio_recorder_compress | bool | false | 录音自动 gzip | true(节省空间) |
db_refresh_interval | int (sec) | 5 | DB 实体刷新周期 | 5(最小) |
ip_auth_reject_if_no_matched | bool | true | IP 鉴权不匹配时静默拒绝 | true(防扫描) |
4.4.2 routing {} —— 路由查表
routing {
schema = switch22 # PostgreSQL schema
function = route_release # 存储过程名
init = init # 初始化存储过程
pass_input_interface_name = true # 把输入接口名传给路由脚本
new_codec_groups = true # 新版 codec group 逻辑
headers {
header(x-yeti-auth)
header(diversion, json, uri_json_array)
header(x-orig-ip, inet)
header(x-orig-port, integer)
header(x-orig-proto, smallint)
# ... 其他透传 header
}
master_pool { host = ... port = 5432 name = yeti user = ... pass = ... size = 4 }
failover_to_slave = false
slave_pool { host = ... port = 5432 name = yeti user = ... pass = ... size = 4 }
}
生产关键:
schema / function / init是 yeti DB schema 内部约定,不要改;master_pool.size= PostgreSQL 连接数,建议 ≥session_processor_threads / 2;- 有只读副本时设
failover_to_slave = true并填slave_pool; headers定义哪些 SIP header 透传给路由存储过程,影响 LCR 策略判断。
4.4.3 cdr {} —— 计费
cdr {
pool_size = 2
auth_pool_size = 2
schema = switch
function = writecdr
master { host = ... port = 5432 name = cdr user = ... pass = ... }
failover_to_slave = false
slave { host = ... port = 5432 name = cdr user = ... pass = ... }
batch_size = 1 # 实时计费通常 1(每次通话立即写)
batch_timeout = 5000 # ms,batch_size 未到上限时的等待上限
auth_batch_size = 1 # 鉴权查询 batch
auth_batch_timeout = 20000
}
4.4.4 resources {} —— Redis 容量/计数器
resources {
reject_on_error = false
write { hosts = { 127.0.0.1:6379 } timeout = 500 }
read { hosts = { 127.0.0.1:6379 } timeout = 1000 }
}
生产关键:
reject_on_error = false(默认):Redis 不可用时降级放行,不阻断通话。电信级建议true+ 多 Redis 哨兵;- 集群部署时
hosts填所有 Redis 节点,SEMS 做 round-robin。
4.5 modules.module "jsonrpc" {} —— JSONRPC(yet-web / yeti-cli 调用)
module "jsonrpc" {
listen { address = 127.0.0.1 port = 7080 }
server_threads = 1
map(yeti.request.registrations.reload, yeti.request.db_states.reload)
# ... 约 10 条 reload 映射
}
⚠️ 安全红线:JSONRPC 端口 7080 必须仅 127.0.0.1 监听,ufw 禁外网。yet-web 与 yeti-cli 是唯一合法调用方,恶意访问可 shutdown SEMS 节点。
4.6 modules.module "redis" {} —— Redis 客户端
module "redis" {
max_batch_size = 10
batch_timeout = 100
max_queue_size = 1000
}
4.7 modules.module "registrar" {} —— SIP Registrar(动态网关 IP)
module "registrar" {
redis {
write { hosts = { 127.0.0.1:6379 } }
read { hosts = { 127.0.0.1:6379 } }
}
headers = { x-orig-ip, x-orig-port, x-orig-proto }
}
五、yeti-web Rails 配置参数详解
5.1 config/database.yml —— PostgreSQL 双库
production:
primary:
adapter: postgresql
encoding: unicode
database: yeti
username: yeti
password: ${DB_PRIMARY_PASS}
host: 127.0.0.1
port: 5432
schema_search_path: 'gui, public, switch, billing, class4, runtime_stats, sys, logs, data_import'
min_messages: notice
pool: 10 # Rails 连接池,SEMS pool_size 另算
# prepared_statements: false # 高并发下可关
cdr:
adapter: postgresql
encoding: unicode
database: cdr
username: cdr
password: ${DB_CDR_PASS}
host: 127.0.0.1
port: 5432
schema_search_path: 'cdr, reports, billing'
min_messages: notice
pool: 10
migrations_paths: db/cdr_migrate
| 参数 | 生产推荐 |
|---|---|
pool | yeti-web Rails 连接池,与 SEMS master_pool.size 独立,Rails 通常 5–10 足够 |
schema_search_path | 必须与 yeti DB schema 匹配,不要删改任何项 |
host | 跨机部署时填数据库 IP |
5.2 config/secrets.yml
production:
secret_key_base: <128 位随机字符串> # pwgen -s 128 1 生成
必须修改,泄露后可伪造 Rails session。
5.3 config/yeti_web.yml —— 业务参数
这是 yeti-web 的核心业务配置文件,从
yeti_web.yml.distr复制后修改。按 1.14 文档与 1.15 changelog 归类:
# 数据库自动维护
maintenance:
auto_vacuum: true
autovacuum_max_workers: 3
autovacuum_naptime: 1min
# CDR 分区
cdr:
retention_days: 90 # CDR 自动保留天数
partition_interval: 1month # CDR 按月分区
# 邮件(Invoice / Email Log)
smtp_connection:
host: smtp.example.com
port: 587
username: invoice@example.com
password: ${SMTP_PASS}
enable_starttls_auto: true
# OAuth/OIDC(1.15 新增)
oauth:
oidc:
enabled: false
# PDF 生成(1.15 新增 yeti-pdf 外部服务)
pdf:
service_url: http://yeti-pdf.local:5000
# S3 存储(1.15 新增:CDR / Invoice 归档)
storage:
s3:
enabled: false
endpoint: s3.example.com
bucket: yeti-archive
access_key_id: ${S3_KEY}
secret_access_key: ${S3_SECRET}
# API 日志
api_log:
enabled: true
retention_days: 30
5.4 Nginx(yet-web 反代)
# 来自 /opt/yeti-web/config/yeti-web.dist.nginx,需根据生产调整
server {
listen 80 default_server;
# Admin API 默认屏蔽,生产改 allow
location /api/rest/admin/ {
allow <管理网段>;
deny all;
proxy_pass http://unix:/run/yeti/yeti-unicorn.sock;
}
location /api/rest/customer/ {
proxy_pass http://unix:/run/yeti/yeti-unicorn.sock;
}
location / {
proxy_pass http://unix:/run/yeti/yeti-unicorn.sock;
}
}
六、Redis 配置
只改一行,其余保持 Ubuntu/Debian 官方默认:
sed -i 's/^notify-keyspace-events.*/notify-keyspace-events "Egx"/' /etc/redis/redis.conf
systemctl restart redis-server
# 验证
redis-cli CONFIG GET notify-keyspace-events
# "notify-keyspace-events" "Egx"
| Redis 关键参数 | 生产推荐 |
|---|---|
notify-keyspace-events | "Egx"(Expired / Generic / String)—— Yeti Registrar incoming registrations 必需 |
maxmemory | 4GB 起(视集群规模,存储 capacity / registrations) |
bind | 127.0.0.1 或具体内网 IP |
protected-mode | yes |
七、PostgreSQL 18 配置
7.1 routing-db 与 cdr-db 建议参数
两个数据库实例配置相同(routing 库低写入高并发,cdr 库高写入批量):
# postgresql.conf 生产关键项
max_connections = 500 # 足够 yeti-web(10) + SEMS(8) + pgqd(2) + 运维
shared_buffers = 4GB # 25% 物理内存(PostgreSQL 经典建议)
effective_cache_size = 12GB # 剩余内存估计
work_mem = 32MB # 排序/哈希中间态
maintenance_work_mem = 2GB # VACUUM / CREATE INDEX
synchronous_commit = on # 电信级计费不建议 off
wal_level = replica
max_wal_senders = 10
wal_buffers = 64MB # 高写入 cdr 库建议加大
checkpoint_completion_target = 0.9
max_wal_size = 8GB
min_wal_size = 2GB
# cdr 库额外:高写入优化
wal_buffers = 256MB
synchronous_commit = on # 计费不建议关
# 路由库可改为 off 降低小事务延迟(有丢失风险)
7.2 pg_hba.conf 关键规则
# routing 库(SEMS + yeti-web 本机访问)
host yeti yeti-web 127.0.0.1/32 scram-sha-256
host yeti yeti 127.0.0.1/32 scram-sha-256
# cdr 库(SEMS + yeti-web 本机访问)
host cdr cdr 127.0.0.1/32 scram-sha-256
# 跨机部署时加对应网段
7.3 pgqd
# /etc/pgqd.ini
[pgqd]
base_connstr = host=127.0.0.1 port=5432 dbname=cdr user=cdr password=q1w2e3r4
initial_database = cdr
database_list = cdr
pidfile = /var/run/postgresql/pgqd.pid
八、生产配置模板
以下三档模板基于 8 vCPU / 16GB RAM / NVMe SSD / 单节点 的规格,供选型参考。
8.1 模板 A:PoC / 小型测试
规格:4 vCPU / 8GB RAM / 20GB SSD / 100 并发以内
# sems.conf 关键段
general { session_processor_threads = 20 media_processor_threads = 4 rtp_receiver_threads = 4 }
media-interfaces { rtp low-port = 16384 high-port = 24576 } # ≈4000 并发
modules.module "yeti" {
master_pool { size = 4 } cdr { batch_size = 1 } resources { write.timeout = 500 }
}
# database.yml pool = 5 / Redis 4GB / shared_buffers = 1GB
8.2 模板 B:中型生产(批发运营商 / 5000 并发)
规格:16 vCPU / 32GB RAM / 500GB NVMe / routing + cdr 分机
# sems.conf
general { session_processor_threads = 60 media_processor_threads = 16 rtp_receiver_threads = 16 }
media-interfaces { rtp low-port = 16384 high-port = 32768 } # ≈8000 并发
modules.module "yeti" {
master_pool { size = 16 } cdr { pool_size = 4 batch_size = 1 batch_timeout = 3000 }
resources { reject_on_error = true }
}
# yeti-web database.yml pool = 10
# Redis maxmemory = 8GB
# PostgreSQL routing: shared_buffers = 8GB / cdr: shared_buffers = 4GB + wal_buffers = 256MB
# pgqd 与 cdr 同机
8.3 模板 C:集群 / Geo 多节点
规格:3+ Switch Node(每个 16 vCPU / 32GB)+ 独立 routing-db + 独立 cdr-db + Redis 哨兵
# 每个 SEMS 节点相同,node_id / pop_id 不同
# SEMS 节点 media_interfaces.address = 节点具体 IP(非 0.0.0.0)
# routing 库 PostgreSQL streaming replication + failovermanager
# cdr 库独立机,pgqd 常驻
# Redis 哨兵 3 节点,SEMS modules.module "redis" hosts 写 3 个地址
# yeti-web 双机 active-passive(keepalived)
九、常见问题
Q1:session_processor_threads 设多少合适?
电信级生产设 40+,session_processor_threads < 并发数 会导致排队丢包。单节点并发上限 ≈ session_processor_threads × 50(经验系数)。
Q2:db_refresh_interval 能调大吗?
可以。10–60 秒可降低 DB 压力,代价是 Web UI 配置变更到 SEMS 生效的延迟。热重载(JSONRPC 主动通知)不受此参数影响。
Q3:routing.master_pool 报 too many connections?
pool.size 设太大(超过 PostgreSQL max_connections)。SEMS 连接数 = session_processor_threads / 2 + db_refresh_interval 相关轮询连接。PostgreSQL 18 默认 max_connections = 100,电信级调 ≥ 500。
Q4:Redis 挂了会影响通话吗?
默认 resources.reject_on_error = false——降级放行,通话继续但容量控制失效(可能超卖)。生产建议 true + Redis 哨兵。
Q5:synchronous_commit = off 在 cdr 库安全吗?
有丢失通话 CDR 的风险(掉电时 WAL 缓冲区未落盘)。电信计费强烈建议 on。可在 routing 库关(丢几秒路由缓存影响小)。
Q6:SEMS node_id 和 yet-web 的 Node 数据库 id 要一致?
不一致!SEMS node_id 是本进程编号(集群内唯一),yet-web Node 数据库 id 是自增主键。yet-web System → Nodes 里填的 Rpc endpoint(127.0.0.1:7080)才是 yet-web 发现本 SEMS 的方式。
十、参考链接
- 1.14 安装指南总览 https://yeti-switch.org/docs/installation/installation-1.14/
- SEMS 配置参考 https://yeti-switch.org/docs/sems/sems.html
- SEMS yeti 内部 https://yeti-switch.org/docs/sems/sems-module-yeti-internals.html
- yeti-web 安装 https://yeti-switch.org/docs/installation/installation-1.14/web.html
- Redis 安装 https://yeti-switch.org/docs/installation/installation-1.14/redis.html
- PostgreSQL 调优 https://yeti-switch.org/docs/advanced/database-tuning.html
- SEMS 安装 https://yeti-switch.org/docs/installation/installation-1.14/sems.html
- Nginx 模板
/opt/yeti-web/config/yeti-web.dist.nginx - Changelog https://yeti-switch.org/docs/changelog.html