Go 1.24 Monorepo,user / catalog / order / merchant 微服务,HTTP 为 go-zero rest + goctl,服务间 zrpc,数据层 sqlx,经 APISIX 统一入口。
Client → APISIX (JWT) → user-service (rest :8881, zrpc :9090)
→ catalog-service (rest :8882, zrpc :9091, Redis, MQ)
→ order-service (rest :8883, zrpc Client → user/catalog/merchant)
→ merchant-service(rest :8884, zrpc :9092)
→ inventory-sync (health :8885, Canal→Redis 库存预热)
- HTTP:go-zero
rest;契约见docs/gozero-http-contract.md - 配置:每服务
internal/config嵌入rest.RestConf,conf.MustLoad+MYMALL_*覆盖 - 同步调用:order → user/catalog/merchant zrpc(goctl rpc:
api/gen+api/rpcclient;可选 etcd) - 边缘网关:APISIX(JWT / 路由 /
X-User-*;刻意不换成 go-zero gateway) - 异步事件:RabbitMQ
mymall.events - 数据层:四业务服务 sqlx;goctl model →
internal/modelgen;schema 靠scripts/*.sql+scripts/ddl/ - 库存:Redis 预扣 + MQ + MySQL;
inventory-sync-service经 Canal 同步 Redis - goctl:见
docs/gozero-migration-runbook.md
mymall/
├── api/proto/ # gRPC 定义(user / catalog / merchant)
├── api/gen/ # goctl/protoc 生成 pb
├── api/rpcclient/ # goctl 生成的 zrpc client
├── pkg/ # 共享库(xerr/jwt/middleware/cache/mq/zrpcx…;database 仅 inventory-sync)
├── common/ # LocalTime 等
├── apps/admin-web/ # 管理端 / 商家端 Vue3
├── apps/mall-uni/ # 用户端 UniApp
├── services/<svc>/
│ ├── api/*.api # goctl HTTP 源
│ ├── etc/<svc>.yaml # RestConf + 业务字段(CONFIG_PATH)
│ ├── internal/modelgen/ # goctl model 实体
│ ├── internal/rpclogic/ # goctl rpc 业务(与 HTTP logic 分离)
│ ├── cmd/main.go # conf.MustLoad + rest + 可选 zrpc
│ └── internal/
│ ├── config/ # RestConf 嵌入
│ ├── handler/ # goctl 生成
│ ├── logic/ # 业务逻辑
│ ├── types/
│ ├── svc/ # ServiceContext(sqlx.Conn / Redis / MQ / RPC)
│ ├── model/ # 表实体(db tag)
│ ├── repository/ # sqlx 数据访问
│ ├── server/ # zrpc 服务端(user/catalog/merchant)
│ └── client/ # zrpc 客户端
├── deploy/
│ ├── k8s/
│ ├── apisix/
│ └── local/docker-compose.yaml
└── scripts/
├── gen-api.sh / generate-proto.sh / gen-model.sh
├── init-*.sql / alter-*.sql / seed-*.sql
└── dev.sh
# MySQL 建库 + 建表(无 migrate 工具,按脚本顺序手动执行;均可重复跑)
mysql -u homestead -p < scripts/migrate-db.sql
mysql -u homestead -p mymall < scripts/init-schema.sql
mysql -u homestead -p mymall < scripts/init-order-tables.sql
# 后台多租户:补 role / shop_id,建 shops 等表
mysql -u homestead -p mymall < scripts/init-merchant-tables.sql
# 种子账号(超管 13900000001 / 商家 13900000002,密码均为 123456)
mysql -u homestead -p mymall < scripts/seed-admin-merchant.sql
# 首页商户(小米/生鲜/服饰 + 门头图;先落盘图片)
bash scripts/seed-home-shop-images.sh
mysql -u homestead -p mymall < scripts/seed-home-shops.sql
# 秒杀场次 + 商家钱包
mysql -u homestead -p --default-character-set=utf8mb4 mymall < scripts/alter-seckill-wallet.sql
# 订单项秒杀关联
mysql -u homestead -p --default-character-set=utf8mb4 mymall < scripts/alter-order-seckill.sql
# 后台 RBAC(菜单/角色/权限)
mysql -u homestead -p mymall < scripts/init-rbac-tables.sql
mysql -u homestead -p --default-character-set=utf8mb4 mymall < scripts/seed-rbac.sql
# 可选:商品中台表结构 + 演示商品(images/ 素材)
# mysql -u homestead -p mymall < scripts/alter-product-center.sql
# python3 scripts/seed-shop-demo-products.py
# Redis + RabbitMQ + Canal(可选 docker-compose)
docker compose -f deploy/local/docker-compose.infra.yaml up -d
# Canal 复制账号(一次即可;需本机 MySQL 已开 ROW binlog)
mysql -u root -p < scripts/init-canal-mysql.sql若基础表早已建好,补 init-merchant-tables.sql + seed-admin-merchant.sql;后台 RBAC 再补 init-rbac-tables.sql + seed-rbac.sql。改代码后需重建对应服务镜像。
本机 MySQL 需开启 ROW binlog(Homestead / 自建均可),例如 my.cnf:
[mysqld]
server-id=1
log-bin=mysql-bin
binlog_format=ROW
binlog_row_image=FULL检查:
mysql -u homestead -p -e "SHOW VARIABLES LIKE 'log_bin'; SHOW VARIABLES LIKE 'binlog_format';"inventory-sync-service 启动时全量预热 product_skus.stock → Redis,随后用 canal-go 增量 CAS 同步。下单路径:Redis 预扣 → MQ → MySQL 乐观锁;inventory.failed / 取消订单会补偿 Redis。
bash scripts/dev.sh inventory # 单独跑 sync
# 或
bash scripts/dev.sh # 含 inventory-sync验证:redis-cli KEYS 'catalog:sku:stock:*';管理端改 SKU 库存后 Redis 应跟随。
表结构变更请执行 scripts/*.sql(四业务服务已不用 GORM AutoMigrate)。
bash scripts/start-all.sh| 服务 | 地址 |
|---|---|
| user-service | http://localhost:8881 |
| catalog-service | http://localhost:8882 |
| order-service | http://localhost:8883 |
| merchant-service | http://localhost:8884 |
| inventory-sync-service | http://localhost:8885 |
| admin-web(Vue) | cd apps/admin-web && npm i && npm run dev → http://localhost:5174 |
| mall-uni(用户端) | cd apps/mall-uni && yarn && yarn dev:h5 → http://localhost:5175 |
停止:bash scripts/stop-all.sh
仅重新构建镜像:bash scripts/build-all.sh
Docker 拉取基础镜像 429? start-all.sh / build-all.sh 已默认走 DaoCloud 镜像源;若仍失败,可手动指定:
export GOLANG_IMAGE=docker.m.daocloud.io/library/golang:1.24-alpine
export ALPINE_IMAGE=docker.m.daocloud.io/library/alpine:3.19
bash scripts/start-all.sh或在 Docker Desktop → Settings → Docker Engine 中移除限流的 registry mirror(如 docker.xuanyuan.me)。
Docker 每次改代码都要重建镜像,日常开发请用 dev.sh(air,保存 .go / .yaml 自动重编重启):
# 只调试正在改的服务(推荐)
bash scripts/dev.sh order
# 或全部服务一起跑(含 inventory-sync)
bash scripts/dev.sh首次会自动 go install github.com/air-verse/air@latest(需 $(go env GOPATH)/bin 在 PATH)。改共享包 pkg/ / common/ 也会触发对应服务重建。前端仍用 cd apps/admin-web && npm run dev(Vite HMR)。
bash deploy/k8s/apply.sh
bash deploy/apisix/install.sh # 首次安装 APISIX
bash deploy/apisix/apply.sh
kubectl port-forward svc/apisix-gateway -n mymall 9080:80注册 → 登录 → 浏览商品 → 下单 → 查订单 → 取消
bash scripts/gen-docs.sh产出:
docs/openapi/mymall.yaml— 整份复制给 AI 生成前端页面docs/openapi/mymall.swagger.json— Swagger 2.0 备份
先在一个终端启动服务(保持运行不要关):
bash scripts/serve-docs.sh再另开浏览器访问: http://localhost:9099/scalar/index.html
若提示「连接被拒绝」,说明文档服务没启动或终端已关闭。
不要直接 open docs/scalar/index.html(file:// 无法加载 yaml)。
各服务开发时也可访问 Swagger UI:http://localhost:8881/swagger/index.html
- 打开 Apifox → 导入 → OpenAPI → 选择
docs/openapi/mymall.yaml - 新建环境 本地开发:
baseUrl=http://localhost:9080(经 APISIX)或http://localhost:8881(直连 user)- 变量
token= 登录后获得的 JWT
- 在「Auth」配置 Bearer Token →
{{token}} - 调试流程:调用
POST /api/v1/user/login→ 复制 token → 再调需鉴权接口 - 每次改接口注释后执行
bash scripts/gen-docs.sh,Apifox 重新导入 同步
以下是商城 OpenAPI 3.0 规范,请生成 Vue3 页面:
- 统一响应 { code, msg, data },code=200 为成功
- JWT: Authorization: Bearer {token}
[粘贴 docs/openapi/mymall.yaml 全文]
可选自动生成 TS 类型:
npx openapi-typescript docs/openapi/mymall.yaml -o frontend/src/types/api.tsbash scripts/generate-proto.sh