7.7 KiB
7.7 KiB
业务前缀重构第 8 步迁移与发布前验收 Runbook
范围
本文用于业务前缀、客户网关匹配和落地号码改写重构的发布前准备。当前仍以本地 KVM/Tailscale 环境为准,不进入阿里云生产迁移。
本步骤覆盖:
- B 执行新增 Prisma migration 前后的检查。
- 旧客户网关单 IP 和旧
customer_gateway_policies到二期模型的安全迁移。 - Redis 配置发布检查。
- A OpenSIPS/Lua 替换前语法检查和回滚点。
- A/B/T 端到端验收清单。
影响、风险与回滚点
影响范围:
- MySQL:新增二期表/列后,
customer_gateways.line_group_id、customer_gateway_ips、customer_gateway_caller_prefixes会被迁移脚本写入。 - Redis:迁移脚本成功应用后会写
customer_gateway_configoutbox,config-publisher 会发布新版本配置。 - OpenSIPS:后续发布 A 侧
opensips.cfg与lisglosips_hotpath.lua后,INVITE 鉴权、路由、主被叫改写进入新热路径。 - CDR:第 7 步已让 Worker 可写入原始被叫、业务前缀、落地主被叫字段。
主要风险:
- 多条旧策略无法自动合并到“一个客户网关一个线路组”,必须人工拆分或确认保留规则。
- 旧
calleeMode=EQUALS/PREFIX不能安全推断为业务前缀,必须先在“业务前缀管理”中建立前缀并重新绑定客户网关。 - 旧
callerMode=EQUALS在新模型下没有严格等值语义,不能自动迁移为前缀,否则可能扩大匹配范围。 - A 侧 OpenSIPS 配置替换会影响现有通话,必须维护窗口或确认可接受。
回滚点:
- B 数据库:执行 migration 前必须按 S30 Runbook 备份 MySQL;迁移脚本 apply 前需保存 dry-run 报告。
- B release:保留当前
/opt/lisglosips/current指向,可通过 S30 rollback 脚本切回旧 release。 - Redis:记录
cfg:active_version与cfg:previous_version,必要时切回上一版本。 - A OpenSIPS:替换前备份
/etc/opensips/opensips.cfg与/etc/opensips/lisglosips_hotpath.lua;语法检查失败不得重启;重启后失败则恢复备份并再次opensips -C。
迁移脚本
本仓库新增:
scripts/phase2-gateway-migration.mjs
默认 dry-run,不写库:
node scripts/phase2-gateway-migration.mjs --json
显式 apply 才写库:
node scripts/phase2-gateway-migration.mjs --apply --json
脚本只自动迁移满足以下条件的客户网关:
- 每个客户网关恰好一条启用旧策略。
- 旧策略
calleeMode=ANY。 - 旧策略
callerMode=ANY,或callerMode=PREFIX且callerValue非空。
脚本会拒绝自动迁移以下情况:
- 多条启用旧策略。
- 没有启用旧策略。
- 旧被叫等值或前缀匹配。
- 旧主叫等值匹配。
- 新旧线路组字段冲突。
apply 成功后,脚本会写入一个 customer_gateway_config outbox,用于触发配置发布。
B 侧发布前步骤
- 记录状态:
readlink -f /opt/lisglosips/current
mysql -NBe "SELECT migration_name, finished_at FROM _prisma_migrations ORDER BY finished_at DESC LIMIT 5;"
redis-cli --no-auth-warning GET cfg:active_version
- 执行 S30 备份:
sudo /opt/lisglosips/current/infra/server-b/s30/lisglosips-release-preflight.sh
sudo /usr/local/sbin/lisglosips-mysql-backup
sudo /usr/local/sbin/lisglosips-redis-backup
-
部署新 release 到独立目录,不在线修改 current。
-
执行数据库 migration:
export DATABASE_URL='mysql://<MIGRATE_USER>@127.0.0.1:3306/lisglosips'
pnpm exec prisma migrate deploy
pnpm exec prisma migrate status
- 迁移脚本 dry-run:
export DATABASE_URL='mysql://<MIGRATE_USER>@127.0.0.1:3306/lisglosips'
node scripts/phase2-gateway-migration.mjs --json > /tmp/phase2-gateway-migration.dry-run.json
-
若
blockers非空,先人工处理,不执行 apply。 -
确认 dry-run 后执行 apply:
node scripts/phase2-gateway-migration.mjs --apply --json > /tmp/phase2-gateway-migration.apply.json
- 等待或触发 config-publisher,检查新配置发布:
systemctl status lisglosips@config-publisher --no-pager
redis-cli --no-auth-warning GET cfg:active_version
A 侧 OpenSIPS 发布前步骤
- 备份:
sudo install -d -m 0750 /var/backups/lisglosips-phase2
sudo cp -a /etc/opensips/opensips.cfg /var/backups/lisglosips-phase2/opensips.cfg.$(date +%Y%m%d%H%M%S)
sudo cp -a /etc/opensips/lisglosips_hotpath.lua /var/backups/lisglosips-phase2/lisglosips_hotpath.lua.$(date +%Y%m%d%H%M%S)
-
替换候选文件后,加载 Lua 并确认 SHA 与
opensips.cfg中EVALSHA一致。 -
必须先执行语法检查:
sudo opensips -C -f /etc/opensips/opensips.cfg
- 语法检查通过后才可重启:
sudo systemctl restart opensips
sudo systemctl is-active opensips
Release Artifact 规范
发布包必须由固定脚本生成,禁止临时手工复制目录作为 release:
pnpm release:artifact -- --release-id sXX-name-YYYYMMDDHHmmss
脚本会执行构建、校验发布必需目录、生成 RELEASE_MANIFEST.json,并输出 dist/releases/<release-id>.tar.gz 与 .sha256。正式给 B 机使用的 artifact 必须在 Linux 环境生成;在本地 Windows 仅允许使用 --check 或带 --allow-non-linux 生成检查包,不能作为服务器最终发布包。
A/B/T 验收清单
至少验证以下呼叫:
- 命中业务前缀:例如客户送
67118822190000,话单callee=18822190000,raw_callee=67118822190000,business_prefix=671。 - 任意被叫规则:客户网关
calleeMatchMode=ANY时,旧无业务前缀呼叫仍可路由。 - 匹配优先级:业务前缀优先于主叫前缀,精确规则优先于空业务前缀兜底;命中业务前缀但主叫不通过时,不应退回裸号兜底网关。
- 唯一性约束:同一 IP + 同一业务前缀组合只能归属一个客户网关;同一 IP 下主叫前缀不能互相覆盖;IP 可跨客户复用但最终匹配必须唯一。
- 计费口径:客户网关决定客户侧计费,落地网关决定供应商侧成本,业务前缀不参与计费产品、报表维度或权限隔离。
- 主叫前缀命中:配置
callerPrefixes后,命中前缀允许呼叫。 - 主叫前缀不命中:返回
CALLER_PREFIX_NOT_MATCHED。 - 业务前缀不命中:返回
BUSINESS_PREFIX_NOT_MATCHED。 - 落地被叫前缀:落地侧实际 Request-URI 被叫包含
landingCalleePrefix。 - 落地指定主叫:落地侧 From 主叫按权重池选择,话单
landing_caller有值。 - 屏蔽地区跳过:命中落地网关屏蔽地区时尝试同线路组下一网关。
- 当前通话页:呼叫过程中可看到当前通话,强制挂断可用。
- 话单详情:可看到原始被叫、业务前缀、落地主叫、落地被叫、地级市、运营商。
回滚
B 应用回滚:
sudo infra/server-b/s30/lisglosips-release-rollback.sh /opt/lisglosips/releases/<previous-release>
Redis 配置回滚:
# 使用当前系统已验证的 Redis 运维方式切回 cfg:previous_version
A OpenSIPS 回滚:
sudo cp -a /var/backups/lisglosips-phase2/<opensips.cfg.backup> /etc/opensips/opensips.cfg
sudo cp -a /var/backups/lisglosips-phase2/<lisglosips_hotpath.lua.backup> /etc/opensips/lisglosips_hotpath.lua
sudo opensips -C -f /etc/opensips/opensips.cfg
sudo systemctl restart opensips
数据库回滚原则:
- 本次 migration 为向前兼容新增表/列,不做破坏性 down migration。
- 若 apply 后发现业务规则错误,优先通过客户网关页面/API 修正
lineGroupId、主叫规则和业务前缀绑定,再重新发布 Redis 配置。 - 若必须恢复数据,使用执行前 MySQL 备份在隔离环境验证后再恢复。