业务故事站
P5 Swift 已实现 PoC

部署运维与授权自检:关停也要优雅

Swift 是 P5 数据导入流水线(先仿真),端口 18084。本主题从部署工程师 / 运维工程师视角讲「上线与合规」:启动流程怎么走、授权到期怎么自动优雅关停本产品而不影响其它产品、AUTH_KEY 怎么配、运维子命令怎么用。用 3 个故事讲清「从拉起来到按规矩关掉」的全过程——每步都有真实端点与 JSON 返回,授权细节与代码一一对应。

运维工程师 部署工程师 系统管理员 授权自检 优雅退出 AUTH_KEY 共 3 个故事

能 / 不能速览

✅ 这个主题能做
  • 启动流程全自动:LoadConfig(fallback 默认值 + env 兜底)→ Bootstrap(PG 优先,ping 失败自动降级 SQLite)→ NewServer → StartLicenseWatcher 授权自检
  • 双路优雅退出:Ctrl+C / SIGTERM 系统信号,或 POST /api/v1/admin/shutdown → httpServer.Shutdown 5s 内完成,不丢账
  • 授权周期自检:启动立即校验 + 每 30 分钟在线校验(LicenseCheckInterval=30min);ShutdownScheduler 幂等评估,授权不满足到点 handleLicenseShutdown 只优雅退出本产品、不影响其它产品
  • AUTH_KEY 三级兜底:DB system_settings → 环境变量 → config.yaml;在线校验 nonce + crypt_data 防重放
  • 运维端点:GET /license/info(force=1 强制重校验,否则 TTL 缓存)、PUT /license/auth-key(内联 admin JWT,成功清缓存)、POST /admin/shutdown
  • 子命令四件套:run(启动)/ service(崩溃 2s 自动重启)/ backup(导出演示数据 JSON 到 stdout)/ health(健康检查,unhealthy 退出码 1)
⛔ 这个主题做不了
  • 在线校验必须外网可达授权服务器(zyinfo.pro:19999),断网时只能给宽限档,无法确认授权(非离线授权)
  • 授权保护的是「进程级」合规(不满足自动关停),不是业务功能级门禁
  • GET /license/info 仅展示机器码与有效期,不做人工关停;关停动作由调度器自动触发
  • service 是简化监管器(2s 重启),非 systemd / 进程守护全功能
  • 无 config.yaml 时 SECRET_KEY 走演示默认值,只能用于演示环境

适用角色

本主题面向三类运维侧角色:

  • 部署工程师:首次部署、启动流程、端口与数据库切换、退出演练(cmd/main.go 与 server/bootstrap.go)。
  • 运维工程师:授权巡检与到期续费、关停调度观察、backup/health 例行作业(license_check.go 与 platform/license)。
  • 系统管理员:授权密钥写入(PUT /license/auth-key)、登录验证、跨产品密钥互认。

能力速览(已实现 PoC)

启动引导 Bootstrap

PG(chatbi_action_dev)优先,ping 失败自动降级 SQLite(data/swift_platform.db);AutoMigrate 建全部表 + 默认管理员 admin/admin1 幂等创建。

授权周期自检 WatchPeriodic

启动立即校验 + 每 30 分钟在线校验(LicenseCheckInterval=30min);Manager TTL 缓存默认 10 分钟,force=1 绕过缓存强制重校验。

关停调度 ShutdownScheduler

幂等评估:未注册 → hard 档(20min+随机 0-10min);已过期不足 30 天 → grace 档(6h+随机 0-2h);过期超 30 天 → hard 档;到期回调 handleLicenseShutdown。

授权密钥 ResolveAuthKey

AUTH_KEY 三级兜底:DB system_settings → 环境变量 → config.yaml security.auth_key;在线校验 nonce+crypt_data(共享 AES 派生密钥解密比对,防重放)。

运维端点

GET /api/v1/license/info(force=1 强制重校验,返回授权与关停状态)、PUT /api/v1/license/auth-key(内联 admin JWT,成功清缓存)、POST /api/v1/admin/shutdown(触发优雅退出)。

运维子命令

run 启动 HTTP 服务 / service 监管模式(崩溃自动重启)/ backup 导出账户·结算·分录·支付 JSON / health 健康检查(unhealthy 退出码 1)。

调整指南(怎么调整)

  • 调整端口:SWIFT_PORT 环境变量优先,其次 config 的 server.port,最后默认 18084。
  • 调整数据库:有 PostgreSQL(DB_* 环境变量 / DATABASE_URL)自动用 PG,不可用自动降级 SQLite;生产建议接真 PG。
  • 调整授权周期:LicenseCheckInterval 默认 30 分钟(watcher.go 常量),测试可传短间隔;TTL 缓存默认 10 分钟(NewManager 可调)。
  • 调整关停档位:grace 宽限 6h + 随机 0-2h、hard 硬关 20min + 随机 0-10min、30 天过期阈值均为 NewShutdownScheduler 默认参数,可按部署策略覆盖。
  • 调整密钥来源:优先写 DB(PUT /license/auth-key 持久化、重启不丢);容器 / 服务编排场景用环境变量 AUTH_KEY 注入。
  • 调整退出方式:手工关停用 POST /api/v1/admin/shutdown(带共享 SECRET_KEY 签发的 admin JWT);脚本 / 任务计划关停发 SIGTERM。

做得好的场景(已实测)

这套部署设计最亮眼的是「无配置也能起、关停真优雅」:
  • 裸机几分钟拉起:LoadConfig fallback + env 兜底,没有 config.yaml 也照常启动,日志明确提示。
  • PG→SQLite 透明降级:Bootstrap 自动探测连接,失败自动切 SQLite 并打 Warn 日志,无需手工改配置。
  • 关停真正优雅:退出双路(信号或 HTTP 指令)汇入 main select → httpServer.Shutdown 5s,数据早已落盘,不丢账。
  • 授权合规自治:到期自动优雅关停本产品、AIP/Foundry/Apollo/Gotham 各产品独立授权互不影响;幂等评估不反复刷新倒计时。
  • 密钥管理收敛:三级兜底一处生效,在线校验 nonce+crypt_data 防重放防伪造,换机器机器码即变。
  • 工具链齐整:run/service/backup/health 四个子命令覆盖启动、自愈、备份、体检,脚本化友好。

限制与不足

以下是明确的边界,先知道再读故事:
  • 在线校验依赖外网:授权服务器在 zyinfo.pro:19999,断网 / 域名不通时只能给宽限档,不能确认授权。
  • 授权形态单一:为「机器码 + 有效期」在线校验(V5 下放能力),不是离线 License 文件 / 加密狗。
  • service 是简化监管器:2s 自动重启,没有 systemd 的依赖管理、日志接管与开机自启。
  • SQLite 是降级方案:Bootstrap 目标是 PostgreSQL,SQLite 只为单机 PoC 兜底。
  • license/info 含演示信息:product_info 的公司 / 微信号为演示数据,不是正式授权公示。

场景故事

故事 1 首次部署:一台没有配置、没有 PostgreSQL 的新机器上把 Swift 拉起来——fallback、降级、双路退出
背景
孙工,部署工程师。客户现场一台新的 Windows 服务器,只有两个环境变量 DEEPSEEK_API_KEY 和 SECRET_KEY,没有 config.yaml、没有 PostgreSQL、连数据库目录都没有。他要在这台"裸机"上把 Swift 拉起并做一次退出演练——验证 LoadConfig fallback、Bootstrap 的 PG→SQLite 降级、双路优雅退出。
传统做法对比
以前部署金融系统要先手工装 PostgreSQL、配 JDBC、写建表脚本、再逐个初始化表,缺一个依赖整个启动就白屏,光排环境问题就大半天。Swift 的 Bootstrap 把建库、AutoMigrate、默认管理员一次做完:PG 连不上自动降级 SQLite(data/swift_platform.db),几分钟就能起来。
角色
部署工程师(首次部署与退出演练);运维工程师(后续巡检);系统管理员(登录验证)。
操作步骤
  1. 把 .env 放到运行目录(可选:DB_* / DEEPSEEK_API_KEY / SECRET_KEY,缺省用默认值兜底)
  2. 运行 ./swift run:LoadConfig 找不到 config.yaml 会打 Warn 并 fallback 默认值 + env 兜底
  3. 观察日志:PG 不可达 → "PostgreSQL unavailable, falling back to SQLite",随后自动建 data/swift_platform.db
  4. 浏览器访问 http://127.0.0.1:18084,GET /health 确认 {"status":"ok","service":"zy-action-swift"}
  5. 用 admin/admin1 登录,确认默认管理员与 admin 角色已幂等就绪
  6. 演练退出:先 Ctrl+C 看信号退出,再重启后调 POST /api/v1/admin/shutdown 看 HTTP 指令退出
系统响应
健康检查真实返回:
GET /health
{"status":"ok","service":"zy-action-swift"}
HTTP 退出指令返回 {"code":0,"message":"shutdown accepted"},main select 双路感知后日志依次出现 "Shutting down Swift server..." 与 "Swift server exited",全程 5s 内完成。
结果洞察
无配置、无 PG 也能起:LoadConfig fallback + env 兜底把"环境缺失"从致命错误降为可选;Bootstrap 的 PG→SQLite 降级让单机 PoC 和联网生产共用同一套代码;双路退出汇入同一 select,SIGTERM 与 HTTP 指令行为一致,数据早已落盘不丢账。
调整建议
生产必须接真 PostgreSQL(配 DB_* 或 DATABASE_URL),别用 SQLite 兜底;端口冲突时用 SWIFT_PORT 换端口(默认 18084);退出演练放在发版窗口做,先 backup 再关停。
动手试一试
删掉 config.yaml 起一次,看 fallback 与降级日志;Ctrl+C 退出后再启动,用 admin JWT 调 POST /api/v1/admin/shutdown 看第二种退出路径;再把 SWIFT_PORT 设为 18085 起第二个实例验证端口优先级。
限制提示
无 config.yaml 时 SECRET_KEY 用演示默认值,只能用于演示环境;SQLite 是降级方案,不是生产目标库;退出演练需确保无在途交易。
故事 2 授权自检与自动关停:到期前 30 分钟自检告警、到期瞬间优雅关停本产品而不影响其它产品
背景
周工,运维工程师。负责的 Swift 演示实例授权 2026-08-29 已过期 1 天。今天 08-30 16:05 的周期自检发现授权不满足,调度器自动安排了关停。他要在到期瞬间验证两件事:一、Swift 能否自己优雅关停;二、同机器上的 AIP / Foundry / Apollo / Gotham 是否毫发无损。
传统做法对比
以前商业软件的授权过期只有两种粗暴处理:要么硬卡死直接拒绝登录(业务全停、现场炸锅),要么过期了还在裸跑(合规风险黑洞)。Swift 的做法是三层合规:未注册直接 hard 档(20min+随机 0-10min);已过期不足 30 天给 grace 宽限档(6h+随机 0-2h),留出续费窗口;过期超过 30 天转 hard 档。到点 handleLicenseShutdown 只优雅退出本产品,各产品独立授权互不拖累。
角色
运维工程师(授权巡检与关停观察);系统管理员(到期续费);部署工程师(关停演练)。
操作步骤
  1. 登录后 GET /api/v1/license/info 查看 authorized / exp_date / hardware_id / auth_key_set
  2. 发现 shutdown_scheduled=true,看 shutdown_tier、shutdown_deadline、shutdown_reason 定位档位与原因
  3. 用 force=1 强制在线重校验一次,绕过 TTL 缓存确认最新授权状态
  4. 等待下一个 30 分钟自检:调度器幂等评估,同档位且 deadline 未到则保持原 deadline,不反复刷新倒计时
  5. 到点 handleLicenseShutdown → 本产品优雅退出;切到 AIP / Foundry / Apollo / Gotham 页面确认其它产品照常服务
  6. 续费后 PUT /api/v1/license/auth-key 写入新密钥 → 调度器取消关停(shutdown_scheduled=false)
系统响应
授权状态真实返回:
GET /api/v1/license/info
{"authorized":false,"exp_date":"2026-08-29","hardware_id":"aip-9f3b2c1d...",
 "auth_key_set":true,"message":"-",
 "product_info":{"name":"ZY Action Platform","company":"深圳展映科技有限公司",
  "date":"2026.8.10","website":"zyinfo.pro","wechat":"youkpan"},
 "shutdown_scheduled":true,"shutdown_deadline":1788134400,
 "shutdown_tier":"grace","shutdown_reason":"授权已过期,请获取注册 KEY 完成续期"}
shutdown_deadline 为 Unix 秒;到期触发后日志打印 "license: 授权不满足,触发本产品优雅退出"。
结果洞察
到期瞬间优雅关停不丢账:httpServer.Shutdown 5s 内完成,账户 / 结算 / 分录早已落库;grace / hard 两档给了 6h 宽限续费窗口,网络校验失败也走宽限而不是直接拒死;幂等评估保证 30 分钟自检不会反复刷新倒计时;最关键的是各产品独立授权,Swift 关停 AIP 等其它产品毫无感知。
调整建议
到期前用监控对 license/info 的 shutdown_deadline 做日历告警,别等自动关停;生产环境 AUTH_KEY 写到 DB 或 env,避免文件丢失;网络不可达会进宽限档,运维要同时盯授权服务器连通性。
动手试一试
把 AUTH_KEY 环境变量临时置空,GET /license/info 看档位变 hard、deadline 约 20 分钟后;再 PUT 回正确密钥,看调度器取消关停(shutdown_scheduled=false);观察期间其它产品的 license/info 是否不受影响。
限制提示
在线校验打外网 zyinfo.pro:19999,断网只能宽限不能确认;TTL 缓存 10 分钟内结果可能滞后,需 force=1 强制重校验;授权保护的是进程级合规,不是业务功能级门禁。
故事 3 授权密钥三级兜底与运维工具链:AUTH_KEY 怎么配、backup / health / service 怎么用
背景
韩总,系统管理员。要给新部署的 Swift 配授权并纳入例行运维。他关心三件事:授权密钥 AUTH_KEY 写在哪里最稳(ResolveAuthKey 三级兜底:DB → env → config.yaml)、数据怎么定时备份(backup 子命令)、进程挂了怎么自愈(service 子命令)+ 怎么体检(health 子命令)。
传统做法对比
以前 License 是放在安装目录的授权文件,容易丢、换机器就失效;授权校验要单独部署服务或写死脚本。Swift 把授权密钥收敛到统一三处:DB(系统设置页可直接写,重启不丢)、环境变量(容器 / 服务编排注入)、config.yaml(本地文件兜底);机器码 = MAC 前 14 字符 + 硬盘序列号 md5,换机器码即变,天然绑定机器。
角色
系统管理员(配置授权密钥与排障);运维工程师(备份 / 健康检查例行作业);部署工程师(service 监管模式)。
操作步骤
  1. 用共享 SECRET_KEY 签发的 admin JWT 调 PUT /api/v1/license/auth-key,body 传 {"auth_key":"..."} 写库
  2. 验证返回 {"code":0,"updated":true},且 system_settings 已落库 AUTH_KEY、授权缓存被清空
  3. 重启服务确认密钥仍在(DB 持久化),GET /license/info 看 auth_key_set=true
  4. ./swift backup 导出账户 / 结算 / 分录 / 支付 JSON 到 stdout,用于定时备份
  5. ./swift health 跑健康检查(config / database / port 三组件),unhealthy 时退出码 1 供监控脚本捕获
  6. ./swift service 启动监管模式:子进程崩溃 2 秒后自动拉起;在线校验用 nonce + crypt_data 防重放防伪造
系统响应
授权密钥写入真实返回:
PUT /api/v1/license/auth-key
{"code":0,"updated":true}
backup 输出 JSON 含 exported_at、product="zy-action-swift" 与 accounts / settlements / journal_entries / payments 四个数组;health 输出组件明细,任一 unhealthy 则进程以退出码 1 结束。
结果洞察
三级兜底让密钥"DB 最优先、容器注入次之、本地文件最后",写库即生效(清缓存强制下次重校验);backup 可进 crontab / 任务计划定时导出;health 是现成的监控探针(unhealthy 退出码 1);service 监管模式适合无人值守现场,崩溃 2 秒自愈。
调整建议
生产建议 AUTH_KEY 走环境变量注入(避免明文写文件);backup 加定时任务并异地保存;health 接监控告警;多实例 / 开机自启场景用 systemd / Windows 任务计划替代简化监管器。
动手试一试
登录后 PUT 一个密钥看 updated=true 与 system_settings 落库;再调 ./swift backup 看四张表 JSON;跑一次 ./swift health 看 config / database / port 三组件状态,再把数据库文件移走验证 unhealthy 退出码。
限制提示
PUT 需内联 admin JWT(共享 SECRET_KEY 签发),非 admin 返回 403;service 是简化监管器,非 systemd 全功能;在线校验需外网可达授权服务器。

常见问题

Swift 多久做一次授权校验?

启动后立即校验一次,之后每 30 分钟周期校验(WatchPeriodic,LicenseCheckInterval=30min)。日常 GET /license/info 默认走 10 分钟 TTL 缓存,带 force=1 参数会强制在线重校验一次。

授权不满足会怎样?

ShutdownScheduler 幂等评估:未注册 → hard 档(20min+随机 0-10min);已过期不足 30 天 → grace 宽限档(6h+随机 0-2h);过期超 30 天 → hard 档;网络校验失败 → grace 档。到点 handleLicenseShutdown 优雅退出本产品,不影响 AIP / Foundry / Apollo / Gotham。

AUTH_KEY 从哪里读?

ResolveAuthKey 三级兜底:先读数据库 system_settings 的 AUTH_KEY,缺失回退环境变量 AUTH_KEY,再回退 config.yaml 的 security.auth_key。在线校验时请求带 hid(机器码前 16 位)+ auth_key + nonce,服务器返回 crypt_data 解密后须与 nonce 一致,防重放。

怎么优雅关停 Swift?

两条路:一、向进程发 SIGINT / SIGTERM(Ctrl+C);二、POST /api/v1/admin/shutdown(带共享 SECRET_KEY 签发的 admin JWT,非本产品 RBAC)。两条路汇入 main select → httpServer.Shutdown,5 秒内完成,数据不丢。

换机器部署会不会影响授权?

会。机器码 = zyaction|MAC 前 14 字符|硬盘序列号的 md5,换机器(网卡或硬盘变化)机器码就变,需要拿新机器码重新申请授权;各产品独立授权,互不影响。部署与组件分工的更多细节见《架构与组件》主题。

主题小结

一句话:Swift 部署 = 启动三连(LoadConfig → Bootstrap → NewServer)后授权自检常驻(启动 + 每 30 分钟在线校验),授权不满足到点优雅关停本产品、其它产品不受影响;运维靠 run / service / backup / health 四个子命令 + /license/info、/license/auth-key、/admin/shutdown 三个端点。记住边界:在线校验需外网,SQLite 是降级方案,service 是简化监管器。