《后端架构设计·架构基础与边界》前言

说明 arch-lab 的定位、范围与目录结构,列出 Go 1.26.0、PostgreSQL 18.4、Docker 29.7.2、Java 21 容器等验证环境,定义 L1–L4 四级可运行标准、代码标记与抽取方式、领域模型与 API 边界,以及本书对实测数字和未覆盖内容的承诺。

这本前言解决什么问题

序讲的是“为什么写”,前言讲的是“怎么用”。具体包括:

  • arch-lab 到底是什么,覆盖哪些范围,不覆盖哪些;
  • 书中代码按什么标准分级,读者需要跑到哪一级;
  • 代码块里的标记是什么意思,怎么抽取、怎么验证;
  • 领域模型、状态机和 API 的边界在哪里;
  • 版本、环境和数字的口径是什么。

如果只想尽快开始读正文,可以先跳到 1.1,遇到代码标记再回来查。但如果你打算把书里的代码真正跑起来,建议先花十分钟读完这篇。

arch-lab 是什么

arch-lab 是一个订单交易系统,用 Go 1.26 编写,围绕订单、库存、支付三个核心概念展开。它的目标不是“做一个能上线的电商系统”,而是提供一个足够小、又能承载完整架构决策的样本。

它包含:

  • 一个订单聚合,带显式状态机和版本号;
  • 一个库存预留模型,支持预留、释放和超时回收;
  • 一个支付模型,支持支付成功、失败和退款;
  • 一组端口接口,隔离存储、库存和支付实现;
  • 内存与 PostgreSQL 两套适配器;
  • 一个基于 outbox 的领域事件发布链路;
  • 一组可执行的依赖、契约和风险检查工具。

它不包含:

  • 用户注册、登录、找回密码等身份功能;
  • 商品管理、购物车、优惠券、发票;
  • 物流轨迹、售后工单、客服系统;
  • 多租户、国际化、复杂权限模型;
  • 生产级的监控、告警、灰度平台。

这些不是“不重要”,而是与卷一的核心问题(边界、决策、可验证性)关系较弱。卷四会把平台工程和治理单独展开。

目录结构

arch-lab 的权威源码在书稿代码块里,不在仓库根目录。抽取后的结构如下:

archlab/
  go.mod                      module archlab,go 1.26.0
  cmd/
    orderd/main.go            装配适配器、启动 HTTP 服务
    loadgen/main.go           卷二使用的压测器
  internal/
    order/                    聚合、状态机、领域事件
    catalog/                  SKU 与价格
    inventory/                库存预留与释放
    payment/                  支付状态与退款
    ports/                    仓储、库存、支付、事件接口
    adapters/
      memory/                 内存实现,用于 L1/L2
      postgres/               PostgreSQL 实现,用于 L3
    platform/
      config/                 配置加载与校验
      httpserver/             路由、中间件、错误映射
      idempotency/            幂等键与去重窗口
  migrations/                 PostgreSQL schema
  testdata/                   固定场景数据
  tools/
    deplint/                  包依赖方向检查
    riskreg/                  风险台账校验
  deploy/
    docker-compose.yml        PostgreSQL 18.4

这个结构对应 1.3 的模块化单体决策:cmd 负责装配,internal 按业务能力分模块,adapters 实现 ports,platform 提供与业务无关的基础设施。

版本与环境

书中所有“实测”结论都基于下面这套环境。版本不同,结果可能不同,尤其是性能数字。

组件版本用途
Go1.26.0全书主线代码
PostgreSQL18.4L3 持久化与事务验证
Docker29.7.2数据库与 Java 21 容器
Java21(Temurin 21.0.13;镜像不可达时用同版本官方包)跨语言对照
Hugo0.163.3+extended书稿构建
操作系统macOS darwin/arm64本机测量环境

几条口径:

  • 本机默认 Java 不是 21,所有 Java 21 结论必须通过容器运行,先确认 java -version;
  • 没有在容器里跑过的 Java 结论,写成“预期行为”,不写“实测”;
  • PostgreSQL 相关结论必须注明是否使用 Docker、是否首次启动、是否有预热;
  • 性能数字必须附命令、并发模型、数据规模和失败率,单次运行不包装成稳定结论。

四级可运行标准

不是每段代码都值得启动数据库。书里把可运行性分成四级,读者可以按需选择验证深度。

L1:纯逻辑或单包

不依赖外部进程,只依赖标准库和项目内包。

验收:

gofmt -l .
go vet ./...
go test ./...

并发代码再加 go test -race ./...。L1 是卷一的默认级别,大部分领域模型、状态机、校验器、端口契约都属于这一级。

L2:进程内端到端

使用 httptest 或 127.0.0.1:0 启动真实 HTTP 服务,适配器用内存实现,不连数据库。

验收:

go test -run TestOrderFlow -v ./...

一个脚本要完成创建、查询、取消三条断言,并检查状态迁移和错误码。第 12 章至少有一个 L2 场景。

L3:真实依赖

使用 Docker Compose 启动 PostgreSQL 18.4,验证事务、条件更新、outbox 和迁移脚本。

验收:

docker compose -f deploy/docker-compose.yml up -d
go test -tags=integration ./...

只承诺实际跑过的场景。没有跑过的数据库行为,写成“预期”或“需要验证”,不写成结论。

L4:多节点与故障注入

多实例、网络分区、主备切换、消息重复与乱序。卷一不承诺 L4,相关内容留给卷三和卷四。书中出现 L4 场景时,会明确标注“需真实环境”,不伪造结果。

代码标记与抽取

书里的 Go 代码块用三行注释标记来源:

// file: internal/order/order.go
// tier: L1
// verify: go test ./internal/order/
package order

三个字段的含义:

字段含义约束
file抽取后的相对路径必须在 arch-lab 目录白名单内,不含 ..
tier运行级别只能是 L1/L2/L3/L4
verify验证命令必须能在抽取后的模块里执行

抽取脚本会按文章分目录,把代码块写入独立模块,避免不同文章的包名和类型互相冲突。这样做的原因是:书稿不是一个大仓库,每篇文章的代码需要能单独编译,读者不必先理解全部上下文。

一个代码块只应包含一个完整文件。不要把同一个文件拆成“上半段/下半段”两个代码块,也不要用“(续)”之类的标记;抽取器会把它当成非法路径。如果确实需要多个文件,就给每个文件一个合法的 file 路径。

领域模型

arch-lab 的核心类型如下:

type Order struct {
	ID         string
	CustomerID string
	Status     Status
	Items      []OrderItem
	TotalCents int64
	Currency   string
	Version    int64
	CreatedAt  time.Time
	UpdatedAt  time.Time
}

type OrderItem struct {
	SKU            string
	Quantity       int
	UnitPriceCents int64
}

状态机:

CREATED ──► INVENTORY_RESERVED ──► PAID ──► FULFILLED
   │                 │               │
   └──► CANCELLED ◄──┘               └──► REFUNDED

约束:

  • 状态只能通过 TransitionTo 修改;
  • 每次修改递增 Version;
  • 非法迁移返回 INVALID_STATE,且不修改聚合;
  • 金额以分为单位,不使用浮点数;
  • 订单创建时计算总额,之后不允许直接改 TotalCents。

这些约束会在第 1、3、6 章反复出现。它们不是“建议”,而是测试会检查的规则。

API 边界

卷一确定五个端点,足够支撑订单主流程,不追求完整电商 API:

方法路径语义
POST/api/v1/orders创建订单,支持 Idempotency-Key
GET/api/v1/orders/{id}查询订单,校验归属
POST/api/v1/orders/{id}/cancel取消订单,按状态机校验
POST/api/v1/orders/{id}/pay支付回调,验签后迁移状态
GET/api/v1/orders?customer_id=&status=&limit=列表查询,分页

错误响应统一为:

{
  "code": "INVALID_STATE",
  "message": "order ord-1 cannot transition from CANCELLED to PAID",
  "request_id": "req-7f3c"
}

code 是契约,调用方按码分支;message 是给人看的,可以改;request_id 用于排查。第 5 章会展开错误模型和版本演进。

测试数据与场景

为了避免每篇文章都造一套数据,arch-lab 固定三组场景:

场景客户商品金额用途
S1 正常下单cus-001sku-book × 14999 分创建、预留、支付、履约
S2 库存不足cus-002sku-limited × 219998 分预留失败、订单取消
S3 重复回调cus-001sku-book × 14999 分幂等、重复支付、对账

书里出现具体数字时,优先复用这三组,避免读者在多个示例之间来回对照。需要新场景时,会在当篇明确说明。

怎么验证一篇的代码

以 1.1 的状态机为例,最小验证流程是:

  1. 从代码块中复制 // file: 标记和代码,放到临时模块的对应路径;
  2. 在模块根目录执行 go mod init archlab,写入 go 1.26.0;
  3. 执行 gofmt -l .、go vet ./...、go test ./...;
  4. 如果失败,先检查 Go 版本和包路径,再检查代码块是否被截断。

书里的代码块都经过这一步验证,但抽取过程可能有复制误差。发现跑不通时,先对照文章中的完整代码块,而不是直接怀疑结论。

关于数字

书里会出现三类数字,读的时候要分清:

类型特征例子
实测值附命令、环境、输出“本机 darwin/arm64,go test -bench 输出如下”
目标值设计目标或 SLO“下单 P99 目标 300ms”
示例参数用于说明配置形状“超时 90 秒后释放库存”

目标值和示例参数不是实测值,不能拿来证明系统性能。反过来,实测值也只代表当次环境,不代表生产容量。卷二会用专门的章节讲怎么设计压测、怎么读结果。

本书不覆盖的内容

  • Go 语言语法、标准库细节;
  • PostgreSQL 安装、调优、备份恢复操作;
  • Kubernetes、服务网格、CI/CD 平台的具体配置;
  • 分布式共识、复制协议、分区算法的推导;
  • 组织变革、绩效管理、招聘。

这些内容分别在语言书、数据库手册、卷三/卷四中处理。卷一只在必要时提到它们,并说明边界。

勘误与反馈

书中的代码、命令和数字都经过本机验证,但环境差异仍然可能导致问题。发现错误时,最有用的反馈是:

  • 你执行的完整命令;
  • 你的环境(Go/Java/PostgreSQL/Docker 版本、操作系统、架构);
  • 完整输出,而不只是“报错了”;
  • 你期望的结果和实际结果的差异。

有了这些信息,才能判断是代码问题、环境问题,还是书里的结论需要修正。

小结

arch-lab 是一个小而有边界的订单系统:三个核心聚合、五个 API、一套状态机、两套适配器、一组可执行检查。书里的代码按 L1–L4 分级,L1 是默认,L2 用于端到端,L3 用于真实数据库,L4 留给后续卷。

记住三条使用约定:代码块带 file/tier/verify 标记;每篇文章的代码应能独立编译;数字要分清实测值、目标值和示例参数。剩下的,从 1.1 开始。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「books」更多文章

  1. 《互联网产品的 AI 架构·平台化与治理》附录 C 平台化评审清单
  2. 《互联网产品的 AI 架构·平台化与治理》附录 B 能力目录与配额字段速查
  3. 《互联网产品的 AI 架构·平台化与治理》附录 A 治理角色与职责速查