Booking Microservices
一个使用 .NET 10 构建的微服务机票预订系统实战项目,采用 Vertical Slice 架构、DDD、CQRS、事件溯源(Event Sourcing)、gRPC、RabbitMQ、Wolverine、PostgreSQL、MongoDB 和 .NET Aspire。
由 Evangelos Vlachos 开发。
目录
概览
该仓库演示了如何端到端地设计和运行一个生产级风格的微服务系统:各服务拥有独立数据库、通过持久化 inbox/outbox 进行异步消息传递、服务间通过 gRPC 同步调用,并包含 API 网关、集中式身份认证、可观测性以及容器/Kubernetes 部署。
主要目标:
- Vertical Slice 架构,按功能划分文件夹。每个请求就是一个自包含的切片。
- 领域驱动设计(DDD) 应用于所有业务逻辑。
- 基于 MediatR 的 CQRS,并配有验证和日志管道行为。
- 事件溯源(EventStoreDB)用于 Booking 服务的写侧。
- 基于 Wolverine 之上的 RabbitMQ 构建的事件驱动架构,采用持久化 inbox(幂等、恰好一次处理)和 outbox(至少一次投递)模式。
- gRPC 用于内部服务间通信。
- PostgreSQL 用于写模型,MongoDB 用于读模型。
- 单元测试、集成测试、端到端测试和契约测试(NSubstitute、Testcontainers、PactNet)。
- 使用 OpenTelemetry、Jaeger、Prometheus、Grafana 以及 Serilog/Kibana 实现可观测性。
- IdentityServer(OpenID Connect / OAuth2)用于身份认证和授权。
- YARP 作为 API 网关。
- Docker Compose、Kubernetes(Nginx Ingress、cert-manager)和 .NET Aspire 用于编排。
架构

每个服务拥有自己的数据,并通过 Minimal API 暴露小规模的 REST 接口。命令修改写存储(PostgreSQL 或 EventStoreDB),并通过 Wolverine 的持久化 outbox 将集成事件发布到 RabbitMQ。消费者通过持久化 inbox 处理这些事件,并将其投影到 MongoDB 读模型。查询只从 MongoDB 读取。必须同步完成的跨服务读取(例如 Booking 校验航班或乘客信息)则通过 gRPC 进行。

服务
| 服务 | 职责 | 写存储 | 读存储 |
|---|---|---|---|
| Identity | 用户、角色、令牌(IdentityServer) | PostgreSQL | - |
| Flight | 航班、机场、飞机、座位 | PostgreSQL | MongoDB |
| Passenger | 乘客资料 | PostgreSQL | MongoDB |
| Booking | 为乘客预订航班座位 | EventStoreDB | MongoDB |
| ApiGateway | 唯一公共入口(YARP) | - | - |
| Aspire AppHost | 本地编排和仪表板 | - | - |
技术栈
- .NET 10、Minimal APIs、API 版本管理
- MediatR、FluentValidation、Mapster
- Wolverine + RabbitMQ 消息传递,MassTransit 契约
- gRPC(基于 Grpc.AspNetCore)
- Entity Framework Core + PostgreSQL
- MongoDB、EventStoreDB、Redis
- Duende IdentityServer(OpenID Connect / OAuth2)
- YARP 反向代理
- OpenTelemetry、Jaeger、Prometheus、Grafana、Serilog + Kibana
- Polly 弹性处理、ASP.NET Core 健康检查
- Scalar 和 Swagger 提供 OpenAPI 文档
- xUnit、NSubstitute、Testcontainers、PactNet、Bogus
- .NET Aspire、Docker、Kubernetes、Nginx Ingress、cert-manager
项目结构
.
├── src
│ ├── ApiGateway/ # YARP 网关
│ ├── Aspire/ # Aspire AppHost 和服务默认配置
│ ├── BuildingBlocks/ # 共享的横切关注点代码(Core、EFCore、Mongo、Wolverine、Jwt、Logging、OpenTelemetry、Polly、TestBase 等)
│ └── Services
│ ├── Booking/ # src/Booking、src/Booking.Api、tests/
│ ├── Flight/
│ ├── Identity/
│ └── Passenger/
├── deployments
│ ├── configs/ # otel-collector、prometheus、grafana 配置
│ ├── docker-compose/ # 基础设施和全栈 compose 文件
│ └── kubernetes/ # 清单 + cert-manager
├── assets/ # 图表和 logo
├── booking.rest # 用于手动 API 测试的 REST Client 请求
└── booking-microservices.sln
在每个服务内部,代码按功能分组(例如 Flights/Features/CreatingFlight/V1/),而不是按技术分层。每个功能文件夹包含其端点、命令/查询、处理器、验证器以及它所发布的事件,因此对一个用例的修改只会涉及该文件夹。
快速开始
前提条件
- .NET 10 SDK
- Docker Desktop
- Node.js(用于 Husky 提交钩子)
- 可选:.NET Aspire CLI、
kubectl
开发证书
创建并信任开发 HTTPS 证书,以便容器能够提供 TLS 服务。
Windows(PowerShell):
dotnet dev-certs https -ep $env:USERPROFILE\.aspnet\https\aspnetapp.pfx -p password
dotnet dev-certs https --trust
macOS / Linux:
dotnet dev-certs https -ep ${HOME}/.aspnet/https/aspnetapp.pfx -p password
dotnet dev-certs https --trust
使用 Aspire 运行
在本地启动全部内容的最快方式,并提供用于查看日志、追踪和指标的仪表板:
aspire run
Aspire 仪表板可通过 http://localhost:18888 访问。
使用 Docker Compose 运行
仅启动基础设施(RabbitMQ、PostgreSQL、EventStoreDB、MongoDB、Redis、Jaeger、Zipkin、OTel Collector、Prometheus、Grafana):
docker-compose -f ./deployments/docker-compose/docker-compose.infrastructure.yaml up -d
启动包含各服务的完整技术栈:
docker-compose -f ./deployments/docker-compose/docker-compose.yaml up -d
使用 Kubernetes 运行
先安装 cert-manager,然后应用 TLS issuer 和应用清单:
kubectl apply -f ./deployments/kubernetes/booking-cert-manager.yml
kubectl apply -f ./deployments/kubernetes/booking-microservices.yml
这些清单引用了
evangelosvlachos96/Docker Hub 命名空间下的镜像。部署前需在该命名空间构建并推送服务镜像(或修改镜像名称)。
手动构建、运行和测试
从仓库根目录构建整个解决方案:
dotnet build
从其 *.Api 项目文件夹运行单个服务(例如 src/Services/Flight/src/Flight.Api):
dotnet run
运行所有测试(集成测试和端到端测试使用 Testcontainers 启动其依赖项,因此必须运行 Docker):
dotnet test
API 文档
每个服务在 /swagger(Swagger UI)和 /scalar/v1(Scalar)提供 OpenAPI 文档。
如需快速手动测试,可使用 VS Code 的 REST Client 扩展打开 booking.rest。预置用户为 van1 / Admin@123456(管理员)和 van2 / User@123456(普通用户)。
开发工具
.NET 工具(CSharpier 格式化器、dotnet-outdated)声明在 .config/dotnet-tools.json 中:
dotnet tool restore
Husky + commitlint 强制执行 Conventional Commits 规范,并在每次提交前运行格式化器:
npm install
升级整个解决方案的 NuGet 包:
dotnet outdated -u
