能在开发机启动只是服务生命周期的开始。交付还要回答:部署的是哪份代码、配置从哪里来、旧版本能否共存、怎样判断异常、数据怎样恢复。这里以单服务为起点;容器与编排工具帮助管理运行过程,不会自动补齐业务恢复能力。

构建一次,运行时提供配置

构建产物应带版本或提交标识并固定依赖。CI 先做编译、测试和必要扫描,再生成不可变产物;同一产物在不同环境使用外部配置。密钥来自受控环境变量或密钥系统,不进入镜像、仓库和日志。运行账号只拥有所需权限。

Java 可以发布可执行 jar;Go 可以发布目标平台的二进制。涉及 CGO、系统证书、时区数据和动态库时,不能假设把文件复制到任意机器都能运行。容器需要合理的 CPU/内存限制、只读文件系统或明确可写目录,并验证信号能到达真正进程。

一次发布的先后顺序

先确认旧程序能接受新增字段或新表,再做兼容迁移;启动新实例,等待就绪,再接流量;停止旧实例接收新工作,等待已接收请求完成,最后退出。迁移带来的数据变化不一定能随应用回滚,所以“保留旧 jar”不等于拥有完整回滚方案。

存活检查判断进程是否需要重启,就绪检查判断是否适合接流量。把所有下游故障都放进存活检查,可能让整组实例在数据库波动时反复重启。对启动慢的服务应单独考虑启动检查和合理等待。

三种信号怎样互相补充

指标适合持续看请求量、错误率、延迟分布、连接池等待、队列年龄和资源饱和;日志保存具体事件;追踪描述一条请求跨组件的因果路径。OpenTelemetry 提供采集和传播的标准接口,本身不等于完整的存储与查询后台。

日志字段可包含 timestamp、level、service、version、requestId/traceId、route、status、durationMs。不要把用户 ID 或完整 URL 当高基数指标标签,也不要把密码、令牌和请求正文直接打进日志。来自外部的请求标识需限制长度和字符,避免日志注入。

症状:p95 延迟升高,CPU 没有升高
指标:数据库连接池 pending 上升,active 持续达到上限
追踪:大部分时间在等待连接,而不是执行 SQL
进一步证据:长事务持有连接等待远程调用
修复方向:缩短事务与下游预算,再复测容量

这是排查示例,不是本项目的性能实测。只有拿到这些证据,才能区分“连接不够”与“连接被过久占用”。

SLO 与压测要观察用户结果

例如“正常预约请求中 99% 在 500 ms 内完成”需要定义统计窗口、什么算正常、超时是否失败以及依赖故障怎样计入。只画平均耗时会掩盖长尾;只看 HTTP 200 又可能漏掉业务失败。设置错误预算后,才有依据在新增功能和可靠性工作之间取舍。

压测从低并发逐步增加,记录吞吐、p50/p95/p99、错误率、资源与下游等待;找到饱和拐点。流量源也可能成为瓶颈,因此负载机与被测服务应区分。不要把一次本机循环请求包装成生产容量结论。

备份必须以恢复完成验收

确定 RPO(可接受丢失的数据量)与 RTO(可接受恢复时长),再选择逻辑备份、物理备份、WAL 归档及恢复策略。数据库副本会复制误删除,不能代替独立备份。定期把备份恢复到隔离环境,校验关键数量与业务流程,并验证密钥、配置和对象文件也能恢复。

交付练习与面试自查

以 Java 预约工程为例,把内存 H2 换成持久 PostgreSQL后,写一份演练记录:启动、预约、备份、隔离恢复、再次读取预约、核对库存和 outbox。演练前先定义可接受损失和耗时;本页不声称已经完成真实服务器恢复。

  • 为什么存活检查不应把所有依赖变慢都当成重启理由?
  • 指标、日志和追踪分别最适合回答什么问题?
  • 应用回滚后读取不了新格式数据,应如何调整迁移与发布设计?

参考资料