Skip to content

发布与部署

Go 单仓库 · Docker Compose · 单 VM 生产 · 向前迁移 · 镜像回滚


发布原则

原则说明
主干可部署合并前必须通过格式化、测试、构建和基础安全检查
镜像不可变每次发布使用 git sha 作为镜像 tag
数据库只向前生产不依赖 down migration 回滚
先备份再迁移涉及 schema 或关键数据变更前先做备份
小步发布每次只发布一个可验证切片,避免同时改订单、支付、库存
可快速回滚代码回滚通过切换旧镜像,数据问题走向前修复或备份恢复

CI Pipeline

步骤命令要求
格式化gofmt -w / CI 检查 diff必须无格式化差异
静态检查go vet ./...必须通过
单元测试go test ./...必须通过
漏洞扫描govulncheck ./...高危阻断发布
Migration 检查migrate -path migrations -database $TEST_DATABASE_URL up临时库可完整迁移
镜像构建docker build -t dingwei/api-server:$GIT_SHA .必须成功
冒烟测试docker compose up -d + health check核心接口可用

核心交易模块还必须有集成测试:下单成功、库存不足、重复下单幂等、支付回调重复通知、支付成功确认库存、30 分钟超时取消、退款成功回滚库存。


Docker Compose 部署

yaml
services:
  api-server:
    image: dingwei/api-server:${APP_VERSION}
    command: ["/app/api-server"]
    ports: ["8080:8080"]
    env_file: .env.production
    depends_on: [postgres, valkey]
    restart: unless-stopped

  admin-api:
    image: dingwei/api-server:${APP_VERSION}
    command: ["/app/admin-api"]
    ports: ["8081:8081"]
    env_file: .env.production
    depends_on: [postgres, valkey]
    restart: unless-stopped

  worker:
    image: dingwei/api-server:${APP_VERSION}
    command: ["/app/worker"]
    env_file: .env.production
    depends_on: [postgres, valkey]
    restart: unless-stopped

  postgres:
    image: postgres:16
    volumes: [pgdata:/var/lib/postgresql/data]
    restart: unless-stopped

  valkey:
    image: valkey/valkey:8
    volumes: [valkeydata:/data]
    restart: unless-stopped

volumes:
  pgdata:
  valkeydata:

api-serveradmin-apiworker 使用同一个镜像,不同启动命令。


发布流程

  1. 合并前跑完整 CI。
  2. 构建镜像:dingwei/api-server:{git_sha}
  3. 推送镜像仓库。
  4. 生产执行发布前备份:pg_dump -Fc 上传 COS。
  5. 停止 worker:避免迁移期间消费旧事件。
  6. 执行 migration:migrate -path migrations -database "$DATABASE_URL" up
  7. 更新 .env.productionAPP_VERSION={git_sha}
  8. 执行 docker compose pull && docker compose up -d
  9. 跑冒烟测试。
  10. 恢复 worker 并观察 30 分钟。

建议发布窗口:周二/周四 14:00-16:00。支付、库存、订单相关发布避开运营高峰。


冒烟测试

检查目标
GET /healthzapi-server 可用
GET /admin/healthzadmin-api 可用
GET /api/products商品列表可读
POST /api/orders/preview计价可用
worker 日志outbox_events 可轮询,无启动错误
指标http_requests_totaloutbox_pending_count 正常暴露

支付回调不能在生产用真实资金随意测试,需提供微信沙箱或固定验签样例进行 staging 验证。


Migration 规范

规则说明
只向前生产不依赖 down 回滚
小步迁移一个 migration 只做一件事
先兼容代码新列先 nullable 或有默认值,代码上线稳定后再收紧
禁止直接删列先废弃,至少一个版本后再删除
大表索引使用 CREATE INDEX CONCURRENTLY
禁止手改生产库所有 schema 变化走 migration
数据修复脚本必须可重复执行、可审计、可回放

命名:

text
migrations/
├── 000001_create_users.up.sql
├── 000001_create_users.down.sql
├── 000002_create_products.up.sql
└── 000002_create_products.down.sql

虽然保留 down 文件用于本地开发,生产故障默认不执行 down。


回滚方案

代码回滚

bash
# 1. 将 APP_VERSION 改回上一个稳定 git sha
vim .env.production

# 2. 重新拉起旧镜像
docker compose pull
docker compose up -d api-server admin-api worker

# 3. 检查健康状态
docker compose ps
docker compose logs --tail=200 api-server worker

数据库问题

场景处理
新增列后代码异常回滚代码,保留新增列
新索引导致性能问题新 migration 删除索引或禁用相关查询
数据修复脚本写错停止写入,基于备份和审计日志评估恢复
破坏性 schema 已执行从备份恢复到新库,对比后人工修复,不直接覆盖生产

回滚决策

症状动作
订单创建错误率 > 5% 持续 5 分钟立即回滚代码
支付回调连续失败停 worker,回滚 payment/order 相关版本,保留回调原文
worker 堆积 > 100 持续 15 分钟暂停新发布,排查后重试或扩 worker
非关键后台 UI 问题走 hotfix,不影响用户端

依赖管理

类型策略
Go patchCI 通过可快速合并
Go minor需要 review changelog 和核心测试
Go major单独排期,写 ADR 或升级说明
安全漏洞高危 24 小时内处理
Docker 基础镜像固定 major/minor,升级前 staging 验证
PostgreSQL / Valkey单独维护窗口,必须有备份和恢复演练

关键依赖:

依赖用途风险
gin-gonic/ginHTTP 路由
jackc/pgxdatabase/sql driverPostgreSQL
redis/go-redisValkey 客户端
golang-migrate/migrate数据库迁移
微信支付适配代码支付签名/验签/退款
vitepress文档站

依赖升级 PR 必须写明:升级原因、breaking changes、验证命令、回滚方式。


发布检查清单

发布前

text
[ ] gofmt / go vet / go test 通过
[ ] govulncheck 无阻断项
[ ] migration 在临时库执行成功
[ ] 已生成并上传 PostgreSQL 备份
[ ] 当前版本号和目标版本号已记录
[ ] 支付、库存、订单相关风险已 review
[ ] 回滚镜像 tag 已确认

发布中

text
[ ] worker 已停止或确认不会处理不兼容事件
[ ] migration 已执行成功
[ ] api-server / admin-api / worker 均已更新
[ ] 健康检查通过
[ ] 冒烟测试通过

发布后

text
[ ] 观察 30 分钟错误率、延迟、支付回调、订单创建、worker 堆积
[ ] 检查 outbox_events failed 数量
[ ] 发布记录写入变更日志
[ ] 如有异常,按回滚矩阵执行

相关链接

鼎味肉市 · 纯线上猪肉零售