Skip to Content

28e - 微服务与 Serverless

本文是《AI Agent 实战手册》第 28 章第 5 节。 上一节:28d-AI辅助认证实现 | 下一节:28f-后端Steering规则与反模式

概述

微服务架构和 Serverless 是现代后端系统的两大核心范式——微服务通过服务拆分实现团队自治和独立部署,Serverless 通过按需执行实现极致弹性和成本优化。在 AI 辅助开发时代,AI 编码助手能够加速服务边界定义、生成服务间通信代码、自动创建 Serverless 函数和部署配置,但微服务的”拆分决策”和 Serverless 的”冷启动优化”仍然需要人工深度参与。本节系统覆盖微服务架构 AI 辅助设计(DDD Bounded Context)、服务间通信模式(REST/gRPC/消息队列)、Serverless 函数 AI 生成(AWS Lambda/Vercel/Cloudflare Workers)、部署配置 AI 生成(Docker/Kubernetes)、API 网关配置,以及断路器与降级策略。


1. 微服务架构 AI 辅助设计

1.1 微服务 vs 单体 vs Serverless:何时选择什么

在开始微服务设计之前,首先需要明确:不是所有项目都需要微服务。AI 倾向于过度拆分服务,这是最常见的陷阱之一。

架构选择决策树: 你的项目处于什么阶段? ├── MVP / 早期创业(< 5 人团队) │ └── 单体优先(Modular Monolith) │ ├── 用 AI 生成模块化的单体架构 │ └── 预留微服务拆分的边界(DDD 模块) ├── 成长期(5-20 人团队,明确的领域边界) │ ├── 核心域独立性要求高? │ │ └── 微服务(按 Bounded Context 拆分) │ ├── 流量波动大,按需计费? │ │ └── Serverless(事件驱动函数) │ └── 混合需求? │ └── 微服务 + Serverless 混合架构 └── 成熟期(20+ 人团队,多团队协作) └── 微服务 + 平台工程 ├── 每个团队拥有 1-3 个服务 └── 内部开发者平台(IDP)统一管理
维度模块化单体微服务Serverless
团队规模1-10 人5-100+ 人1-20 人
部署复杂度⭐ 低⭐⭐⭐⭐ 高⭐⭐ 中
运维成本⭐ 低⭐⭐⭐⭐ 高⭐ 低(托管)
独立部署❌ 整体部署✅ 服务级独立✅ 函数级独立
技术异构❌ 统一技术栈✅ 每服务可不同⚠️ 受平台限制
冷启动❌ 无❌ 无⚠️ 有(需优化)
成本模型固定(服务器)固定(多服务器)按调用量计费
AI 辅助效果⭐⭐⭐⭐⭐ 极好⭐⭐⭐ 中等⭐⭐⭐⭐ 好
适用场景MVP、中小项目大型系统、多团队事件驱动、API 后端

1.2 工具推荐

工具用途核心能力价格适用场景
Claude CodeAI 辅助微服务设计全项目理解、多文件编辑、DDD 分析、服务拆分建议$20/月(Max 5x)/ API 按量微服务架构设计、跨服务重构
KiroSpec 驱动微服务开发需求→设计→任务的结构化流程、Steering 规则免费(预览期)结构化微服务开发、服务契约定义
BufProtobuf/gRPC 管理Schema 管理、代码生成、Breaking Change 检测、Lint免费(开源)/ $75/月(Teams)gRPC 微服务的 API 契约管理
Kong GatewayAPI 网关路由、限流、认证、插件生态、声明式配置免费(开源)/ 联系销售(Enterprise)微服务 API 网关、流量管理
Traefik反向代理/API 网关自动服务发现、Let’s Encrypt、Docker/K8s 原生免费(开源)/ 联系销售(Enterprise)容器化微服务的动态路由
APISIXAPI 网关高性能、插件化、多协议(HTTP/gRPC/WebSocket)免费(开源)高性能 API 网关需求
Temporal工作流引擎分布式工作流编排、Saga 模式、重试、可观测性免费(开源)/ 联系销售(Cloud)微服务编排、分布式事务
NATS消息系统轻量级消息队列、JetStream 持久化、请求-回复免费(开源)/ 联系销售(Synadia Cloud)微服务间异步通信
RabbitMQ消息队列AMQP 协议、多种交换模式、管理 UI、集群免费(开源)/ $99/月起(CloudAMQP)可靠消息传递、任务队列
Apache Kafka事件流平台高吞吐事件流、持久化、消费者组、Kafka Streams免费(开源)/ $0.10/GB起(Confluent Cloud)事件溯源、高吞吐数据管线
SST (Serverless Stack)Serverless 框架TypeScript 优先、AWS CDK 封装、本地开发、实时日志免费(开源)AWS Serverless 全栈开发
Serverless FrameworkServerless 部署多云支持、插件生态、离线开发免费(开源)/ $15/月起(Dashboard)多云 Serverless 部署
PulumiIaC 平台通用编程语言(TS/Python/Go)、AI Assist免费(个人)/ $50/月起(Team)用代码定义微服务基础设施
Istio服务网格流量管理、安全(mTLS)、可观测性、故障注入免费(开源)大规模微服务的网络治理
Linkerd服务网格轻量级、Rust 数据平面、自动 mTLS、低资源占用免费(开源)/ 联系销售(Enterprise)轻量级服务网格需求

1.3 DDD Bounded Context 与服务边界定义

领域驱动设计(DDD)是微服务边界定义的核心方法论。AI 可以辅助识别 Bounded Context,但最终的拆分决策需要人工判断。

DDD 核心概念与微服务映射: ┌─────────────────────────────────────────────────────────────┐ │ 业务领域(Domain) │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Bounded │ │ Bounded │ │ Bounded │ │ │ │ Context A │ │ Context B │ │ Context C │ │ │ │ │ │ │ │ │ │ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ │ │ │ 聚合根 A1 │ │ │ │ 聚合根 B1 │ │ │ │ 聚合根 C1 │ │ │ │ │ │ ├─实体 │ │ │ │ ├─实体 │ │ │ │ ├─实体 │ │ │ │ │ │ └─值对象 │ │ │ │ └─值对象 │ │ │ │ └─值对象 │ │ │ │ │ └──────────┘ │ │ └──────────┘ │ │ └──────────┘ │ │ │ │ │ │ │ │ │ │ │ │ → 微服务 A │ │ → 微服务 B │ │ → 微服务 C │ │ │ │ 独立数据库 │ │ 独立数据库 │ │ 独立数据库 │ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ │ │ │ └────── API / 事件 ─┴────── API / 事件 ┘ │ │ │ │ 关键原则: │ │ • 每个 Bounded Context = 一个微服务 │ │ • 每个微服务拥有自己的数据库(Database per Service) │ │ • 服务间通过 API 或事件通信,不共享数据库 │ │ • 同一概念在不同 Context 中可以有不同含义 │ │ (如"用户"在认证服务是 Credential,在订单服务是 Customer) │ │ │ └─────────────────────────────────────────────────────────────┘

1.4 操作步骤:AI 辅助识别 Bounded Context

步骤 1:用 AI 分析业务领域

提示词模板:识别 Bounded Context

你是一位领域驱动设计(DDD)专家。请分析以下业务领域,识别 Bounded Context 并建议微服务拆分方案。 ## 业务描述 [详细描述你的业务领域、核心流程、用户角色] ## 分析要求 1. 识别核心域(Core Domain)、支撑域(Supporting Domain)、通用域(Generic Domain) 2. 为每个域定义 Bounded Context,说明: - 上下文名称和职责 - 核心聚合根(Aggregate Root) - 关键实体和值对象 - 领域事件(Domain Events) 3. 绘制上下文映射图(Context Map),标注关系类型: - 合作关系(Partnership) - 客户-供应商(Customer-Supplier) - 防腐层(Anti-Corruption Layer) - 开放主机服务(Open Host Service) - 共享内核(Shared Kernel) 4. 建议每个 Bounded Context 对应的微服务 5. 标注哪些服务可以合并(避免过度拆分) ## 约束条件 - 团队规模:[人数] - 预期 QPS:[数值] - 数据一致性要求:[强一致/最终一致] ## 输出格式 1. 领域分析表(域类型、Bounded Context、聚合根、领域事件) 2. 上下文映射图(Mermaid 格式) 3. 微服务拆分建议(服务名、职责、数据库、通信方式) 4. 拆分风险评估(哪些拆分可能过度,建议合并的理由)

步骤 2:验证服务边界

AI 生成的 Bounded Context 需要通过以下检查验证:

服务边界验证清单: ✅ 独立性检查 □ 该服务能否独立部署,不影响其他服务? □ 该服务能否独立扩缩容? □ 该服务的数据库能否独立迁移? ✅ 内聚性检查 □ 服务内的所有功能是否围绕同一业务能力? □ 是否存在"上帝服务"(承担过多职责)? □ 修改一个业务规则是否只需要改一个服务? ✅ 耦合度检查 □ 服务间是否存在循环依赖? □ 一个请求是否需要调用超过 3 个服务?(如果是,考虑合并) □ 服务间是否共享数据库表?(如果是,边界有问题) ✅ 团队对齐检查 □ 每个服务是否可以由一个小团队(2-8 人)独立维护? □ 服务边界是否与团队边界对齐?(康威定律) ✅ 数据所有权检查 □ 每条数据是否有且只有一个服务拥有? □ 其他服务是否通过 API 或事件获取数据副本? □ 是否存在跨服务的事务需求?(如果是,考虑 Saga 模式)

步骤 3:生成服务骨架

提示词模板:生成微服务项目骨架

你是一位微服务架构师。请为以下微服务生成项目骨架代码。 ## 服务信息 - 服务名称:[服务名] - Bounded Context:[上下文描述] - 核心聚合根:[聚合根列表] - 领域事件:[事件列表] ## 技术栈 - 语言/框架:[例如 TypeScript + NestJS / Go + Gin / Python + FastAPI] - 数据库:[例如 PostgreSQL / MongoDB] - 消息队列:[例如 RabbitMQ / Kafka / NATS] - API 风格:[REST / gRPC / 混合] ## 项目结构要求 采用六边形架构(Hexagonal Architecture):

src/ ├── domain/ # 领域层(纯业务逻辑,无外部依赖) │ ├── entities/ # 实体和聚合根 │ ├── value-objects/ # 值对象 │ ├── events/ # 领域事件 │ ├── repositories/ # 仓储接口(端口) │ └── services/ # 领域服务 ├── application/ # 应用层(用例编排) │ ├── commands/ # 命令处理器 │ ├── queries/ # 查询处理器 │ └── dto/ # 数据传输对象 ├── infrastructure/ # 基础设施层(适配器) │ ├── persistence/ # 数据库实现 │ ├── messaging/ # 消息队列实现 │ └── http/ # HTTP 客户端 └── interfaces/ # 接口层(入站适配器) ├── rest/ # REST API 控制器 ├── grpc/ # gRPC 服务实现 └── events/ # 事件消费者

## 必须包含 1. 领域实体和聚合根(含业务规则验证) 2. 仓储接口和内存实现(用于测试) 3. 至少一个命令处理器和查询处理器 4. 领域事件定义和发布机制 5. REST API 端点(CRUD + 业务操作) 6. Docker 配置(Dockerfile + docker-compose.yml) 7. 单元测试骨架

1.5 AI 辅助微服务设计的能力边界

任务AI 能力说明
识别 Bounded Context⭐⭐⭐AI 能给出合理的初始建议,但需要领域专家验证
生成服务骨架代码⭐⭐⭐⭐标准化的项目结构和样板代码,AI 表现优秀
定义领域事件⭐⭐⭐AI 能识别常见事件,但可能遗漏业务特有的事件
设计上下文映射⭐⭐服务间关系的微妙之处需要人工判断
决定拆分粒度⭐⭐AI 倾向于过度拆分,需要人工约束
处理分布式事务⭐⭐Saga 模式的补偿逻辑需要深入理解业务
数据一致性策略⭐⭐最终一致性的边界条件需要人工分析

2. 服务间通信模式

2.1 通信方式全景对比

微服务间的通信方式选择直接影响系统的性能、可靠性和复杂度:

通信方式类型延迟可靠性耦合度适用场景AI 生成质量
REST(HTTP/JSON)同步中等(1-10ms)CRUD 操作、简单查询、外部 API⭐⭐⭐⭐⭐
gRPC(HTTP/2 + Protobuf)同步/流式低(0.5-5ms)内部服务通信、高性能场景、流式数据⭐⭐⭐⭐
消息队列(RabbitMQ/NATS)异步高(10-100ms)事件通知、任务分发、解耦⭐⭐⭐
事件流(Kafka)异步高(10-100ms)极高极低事件溯源、数据管线、审计日志⭐⭐⭐
GraphQL Federation同步中等前端聚合多服务数据⭐⭐⭐
WebSocket双向极低实时通知、聊天、协作编辑⭐⭐⭐
通信方式选择决策树: 调用方需要立即获得结果吗? ├── 是(同步) │ ├── 内部服务间通信? │ │ ├── 高性能要求(< 5ms)→ gRPC │ │ └── 简单 CRUD → REST │ └── 外部客户端? │ ├── 多服务数据聚合 → GraphQL Federation │ └── 单服务调用 → REST └── 否(异步) ├── 需要消息持久化和重放? │ └── Kafka(事件流) ├── 需要复杂路由(topic/fanout)? │ └── RabbitMQ ├── 需要轻量级、低延迟? │ └── NATS └── 需要实时双向通信? └── WebSocket / SSE

2.2 REST 通信:AI 生成服务间 HTTP 客户端

REST 是最常见的微服务通信方式,AI 对 REST 模式的理解最为成熟。

提示词模板:生成类型安全的服务间 HTTP 客户端

你是一位微服务后端专家。请为 [服务A] 生成调用 [服务B] 的类型安全 HTTP 客户端。 ## 服务 B 的 API 端点 [列出服务 B 的 API 端点、请求/响应类型] ## 技术要求 - 语言:TypeScript - HTTP 客户端:[fetch / axios / ky / got] - 重试策略:指数退避,最多 3 次 - 超时:[例如 5 秒] - 断路器:[是/否] ## 必须包含 1. 请求/响应的 TypeScript 类型定义 2. 统一的错误处理(网络错误、超时、4xx、5xx) 3. 请求重试逻辑(仅对幂等操作重试) 4. 请求日志(不记录敏感信息) 5. 请求追踪(传递 trace-id header) 6. 健康检查端点调用 7. 连接池配置(如适用)

服务间 REST 通信示例

// ============================================ // clients/order-service.client.ts // 订单服务 → 库存服务的 HTTP 客户端 // ============================================ interface InventoryCheckRequest { productId: string; quantity: number; } interface InventoryCheckResponse { available: boolean; currentStock: number; reservationId?: string; } interface ServiceClientConfig { baseUrl: string; timeout: number; retries: number; circuitBreaker: { threshold: number; // 失败阈值(触发熔断) resetTimeout: number; // 熔断恢复时间(ms) }; } class InventoryServiceClient { private failures = 0; private circuitOpen = false; private circuitOpenTime = 0; constructor(private readonly config: ServiceClientConfig) {} /** * 检查库存可用性 * 通信要点: * 1. 传递 trace-id 实现分布式追踪 * 2. 设置合理超时(避免级联超时) * 3. 幂等操作自动重试 * 4. 断路器防止级联故障 */ async checkAvailability( request: InventoryCheckRequest, traceId: string, ): Promise<InventoryCheckResponse> { // 断路器检查 if (this.isCircuitOpen()) { throw new ServiceUnavailableError( 'inventory-service', '库存服务暂时不可用(断路器已打开)', ); } const url = `${this.config.baseUrl}/api/v1/inventory/check`; for (let attempt = 1; attempt <= this.config.retries; attempt++) { try { const controller = new AbortController(); const timeoutId = setTimeout( () => controller.abort(), this.config.timeout, ); const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Trace-Id': traceId, 'X-Source-Service': 'order-service', }, body: JSON.stringify(request), signal: controller.signal, }); clearTimeout(timeoutId); if (!response.ok) { // 4xx 错误不重试(客户端错误) if (response.status >= 400 && response.status < 500) { const error = await response.json(); throw new ClientError(response.status, error.message); } // 5xx 错误重试 throw new ServerError(response.status, 'inventory-service'); } // 成功:重置断路器计数 this.resetCircuitBreaker(); return await response.json() as InventoryCheckResponse; } catch (error) { if (error instanceof ClientError) throw error; // 不重试 // 记录失败 this.recordFailure(); if (attempt === this.config.retries) { throw new ServiceUnavailableError( 'inventory-service', `库存服务调用失败(已重试 ${this.config.retries} 次)`, ); } // 指数退避等待 const delay = Math.min(1000 * Math.pow(2, attempt - 1), 5000); await new Promise(resolve => setTimeout(resolve, delay)); } } throw new ServiceUnavailableError('inventory-service', '未知错误'); } private isCircuitOpen(): boolean { if (!this.circuitOpen) return false; // 半开状态:超过恢复时间后允许一次尝试 if (Date.now() - this.circuitOpenTime > this.config.circuitBreaker.resetTimeout) { this.circuitOpen = false; this.failures = 0; return false; } return true; } private recordFailure(): void { this.failures++; if (this.failures >= this.config.circuitBreaker.threshold) { this.circuitOpen = true; this.circuitOpenTime = Date.now(); } } private resetCircuitBreaker(): void { this.failures = 0; this.circuitOpen = false; } }

2.3 gRPC 通信:AI 生成 Protobuf 定义和服务代码

gRPC 适用于内部服务间的高性能通信,使用 Protocol Buffers 作为接口定义语言(IDL)。

提示词模板:生成 gRPC 服务定义

你是一位 gRPC 专家。请为以下微服务间通信生成 Protocol Buffers 定义和服务实现。 ## 通信需求 - 调用方服务:[服务名] - 被调用服务:[服务名] - 通信场景:[描述具体的通信需求] ## 技术栈 - 语言:[TypeScript / Go / Python / Java] - gRPC 框架:[nice-grpc / grpc-go / grpcio / grpc-java] - Protobuf 管理:[Buf / protoc] ## 要求 1. .proto 文件定义(包含 service、message、enum) 2. 服务端实现(包含错误处理和日志) 3. 客户端实现(包含重试和超时) 4. 使用 Buf 的 lint 规则确保 API 质量 5. 包含健康检查服务(grpc.health.v1) 6. 支持 deadline 传播(上游超时传递给下游) ## gRPC 通信模式 - [ ] Unary RPC(一请求一响应) - [ ] Server Streaming(服务端流式响应) - [ ] Client Streaming(客户端流式请求) - [ ] Bidirectional Streaming(双向流式)

gRPC Protobuf 定义示例

// ============================================ // proto/inventory/v1/inventory.proto // 库存服务 gRPC 接口定义 // ============================================ syntax = "proto3"; package inventory.v1; option go_package = "github.com/myapp/inventory/v1;inventoryv1"; // 库存服务 service InventoryService { // 检查库存可用性(Unary RPC) rpc CheckAvailability(CheckAvailabilityRequest) returns (CheckAvailabilityResponse); // 预留库存(Unary RPC) rpc ReserveStock(ReserveStockRequest) returns (ReserveStockResponse); // 释放预留(Unary RPC) rpc ReleaseReservation(ReleaseReservationRequest) returns (ReleaseReservationResponse); // 批量查询库存(Server Streaming) rpc BatchCheckAvailability(BatchCheckRequest) returns (stream CheckAvailabilityResponse); } message CheckAvailabilityRequest { string product_id = 1; int32 quantity = 2; } message CheckAvailabilityResponse { bool available = 1; int32 current_stock = 2; string reservation_id = 3; // 可选:预留 ID } message ReserveStockRequest { string product_id = 1; int32 quantity = 2; string order_id = 3; // 关联订单 ID(幂等键) int32 ttl_seconds = 4; // 预留有效期 } message ReserveStockResponse { string reservation_id = 1; google.protobuf.Timestamp expires_at = 2; } message ReleaseReservationRequest { string reservation_id = 1; } message ReleaseReservationResponse { bool success = 1; } message BatchCheckRequest { repeated CheckAvailabilityRequest items = 1; }

gRPC 客户端实现示例(Go)

// ============================================ // clients/inventory_client.go // 订单服务中的库存 gRPC 客户端 // ============================================ package clients import ( "context" "time" inventoryv1 "github.com/myapp/inventory/v1" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) type InventoryClient struct { client inventoryv1.InventoryServiceClient conn *grpc.ClientConn } func NewInventoryClient(addr string) (*InventoryClient, error) { conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()), // 重试策略 grpc.WithDefaultServiceConfig(`{ "methodConfig": [{ "name": [{"service": "inventory.v1.InventoryService"}], "retryPolicy": { "maxAttempts": 3, "initialBackoff": "0.1s", "maxBackoff": "1s", "backoffMultiplier": 2, "retryableStatusCodes": ["UNAVAILABLE", "DEADLINE_EXCEEDED"] } }] }`), ) if err != nil { return nil, err } return &InventoryClient{ client: inventoryv1.NewInventoryServiceClient(conn), conn: conn, }, nil } // CheckAvailability 检查库存 // 通信要点: // 1. 设置 deadline(超时传播) // 2. 传递 trace-id(分布式追踪) // 3. 处理 gRPC 状态码 func (c *InventoryClient) CheckAvailability( ctx context.Context, productID string, quantity int32, traceID string, ) (*inventoryv1.CheckAvailabilityResponse, error) { // 设置 deadline(如果上游没有设置) if _, ok := ctx.Deadline(); !ok { var cancel context.CancelFunc ctx, cancel = context.WithTimeout(ctx, 3*time.Second) defer cancel() } // 传递追踪信息 ctx = metadata.AppendToOutgoingContext(ctx, "x-trace-id", traceID, "x-source-service", "order-service", ) resp, err := c.client.CheckAvailability(ctx, &inventoryv1.CheckAvailabilityRequest{ ProductId: productID, Quantity: quantity, }, ) if err != nil { return nil, c.handleError(err) } return resp, nil } func (c *InventoryClient) handleError(err error) error { st, ok := status.FromError(err) if !ok { return fmt.Errorf("inventory service: unknown error: %w", err) } switch st.Code() { case codes.NotFound: return ErrProductNotFound case codes.ResourceExhausted: return ErrInsufficientStock case codes.DeadlineExceeded: return ErrServiceTimeout case codes.Unavailable: return ErrServiceUnavailable default: return fmt.Errorf("inventory service: %s", st.Message()) } } func (c *InventoryClient) Close() error { return c.conn.Close() }

2.4 消息队列通信:AI 生成事件驱动架构

异步消息通信是微服务解耦的核心手段。AI 可以辅助生成事件定义、生产者和消费者代码。

消息队列选型对比

特性RabbitMQApache KafkaNATSRedis Streams
协议AMQP 0-9-1自定义(TCP)自定义(TCP)RESP
消息模型队列 + 交换器分区日志发布-订阅 + 队列追加日志
消息持久化✅ 可选✅ 默认持久化✅ JetStream✅ 默认持久化
消息重放❌ 消费即删除✅ 按偏移量重放✅ JetStream✅ 按 ID 重放
消息顺序✅ 队列内有序✅ 分区内有序⚠️ 有限保证✅ 流内有序
吞吐量万级/秒百万级/秒百万级/秒十万级/秒
延迟1-10ms5-50ms< 1ms1-5ms
运维复杂度⭐⭐ 中⭐⭐⭐⭐ 高⭐ 低⭐ 低
适用场景任务队列、RPC事件流、数据管线轻量级消息简单队列、缓存层
托管服务CloudAMQPConfluent CloudSynadia CloudUpstash
价格(托管)$99/月起$0.10/GB起联系销售按用量(免费额度)

提示词模板:生成事件驱动通信代码

你是一位事件驱动架构专家。请为以下微服务间的异步通信生成代码。 ## 通信场景 - 事件生产者:[服务名] - 事件消费者:[服务名列表] - 业务场景:[描述事件触发条件和消费者行为] ## 技术栈 - 消息队列:[RabbitMQ / Kafka / NATS] - 语言:[TypeScript / Go / Python] - 序列化:[JSON / Protobuf / Avro] ## 要求 1. 事件 Schema 定义(包含版本号、时间戳、trace-id) 2. 事件生产者(发布事件,确保至少一次投递) 3. 事件消费者(消费事件,实现幂等处理) 4. 死信队列(DLQ)处理失败消息 5. 消息重试策略(指数退避,最多 5 次) 6. 消费者组配置(多实例并行消费) 7. 事件 Schema 演进策略(向后兼容) ## 幂等性要求 消费者必须实现幂等处理: - 使用事件 ID 去重 - 使用数据库唯一约束防止重复处理 - 处理乱序消息的策略

事件驱动通信示例(TypeScript + RabbitMQ)

// ============================================ // events/order-events.ts —— 领域事件定义 // ============================================ // 事件基类:所有领域事件的标准结构 interface DomainEvent<T = unknown> { eventId: string; // 唯一事件 ID(UUID) eventType: string; // 事件类型 version: number; // Schema 版本(用于演进) timestamp: string; // ISO 8601 时间戳 traceId: string; // 分布式追踪 ID source: string; // 来源服务 data: T; // 事件数据 } // 订单已创建事件 interface OrderCreatedEvent extends DomainEvent<{ orderId: string; customerId: string; items: Array<{ productId: string; quantity: number; unitPrice: number; }>; totalAmount: number; }> { eventType: 'order.created'; version: 1; } // 订单已支付事件 interface OrderPaidEvent extends DomainEvent<{ orderId: string; paymentId: string; amount: number; paidAt: string; }> { eventType: 'order.paid'; version: 1; }
// ============================================ // messaging/event-publisher.ts —— 事件发布者 // ============================================ import amqp from 'amqplib'; import { randomUUID } from 'crypto'; class EventPublisher { private channel: amqp.Channel | null = null; constructor( private readonly connectionUrl: string, private readonly exchange: string = 'domain-events', ) {} async connect(): Promise<void> { const connection = await amqp.connect(this.connectionUrl); this.channel = await connection.createChannel(); // 声明 topic 交换器(支持路由键模式匹配) await this.channel.assertExchange(this.exchange, 'topic', { durable: true, // 持久化交换器 }); } /** * 发布领域事件 * 可靠性要点: * 1. 消息持久化(deliveryMode: 2) * 2. 使用 confirm 模式确保消息到达 broker * 3. 路由键格式:{aggregate}.{event}(如 order.created) */ async publish<T>(event: DomainEvent<T>): Promise<void> { if (!this.channel) throw new Error('Publisher not connected'); const routingKey = event.eventType; // e.g., "order.created" const message = Buffer.from(JSON.stringify(event)); this.channel.publish(this.exchange, routingKey, message, { persistent: true, // 消息持久化 messageId: event.eventId, // 用于去重 timestamp: Date.now(), headers: { 'x-trace-id': event.traceId, 'x-event-version': event.version, 'x-source-service': event.source, }, }); } // 辅助方法:创建标准事件 createEvent<T>( eventType: string, data: T, traceId: string, ): DomainEvent<T> { return { eventId: randomUUID(), eventType, version: 1, timestamp: new Date().toISOString(), traceId, source: process.env.SERVICE_NAME ?? 'unknown', data, }; } }
// ============================================ // messaging/event-consumer.ts —— 事件消费者 // ============================================ import amqp from 'amqplib'; interface ConsumerConfig { queue: string; // 队列名 routingKeys: string[]; // 订阅的路由键模式 prefetch: number; // 预取数量(并发控制) maxRetries: number; // 最大重试次数 } class EventConsumer { private channel: amqp.Channel | null = null; constructor( private readonly connectionUrl: string, private readonly exchange: string = 'domain-events', private readonly config: ConsumerConfig, ) {} async connect(): Promise<void> { const connection = await amqp.connect(this.connectionUrl); this.channel = await connection.createChannel(); // 设置预取(控制并发消费数量) await this.channel.prefetch(this.config.prefetch); // 声明队列 await this.channel.assertQueue(this.config.queue, { durable: true, arguments: { // 死信队列配置 'x-dead-letter-exchange': `${this.exchange}.dlx`, 'x-dead-letter-routing-key': this.config.queue, }, }); // 声明死信交换器和队列 await this.channel.assertExchange(`${this.exchange}.dlx`, 'direct', { durable: true, }); await this.channel.assertQueue(`${this.config.queue}.dlq`, { durable: true, }); await this.channel.bindQueue( `${this.config.queue}.dlq`, `${this.exchange}.dlx`, this.config.queue, ); // 绑定路由键 for (const key of this.config.routingKeys) { await this.channel.bindQueue( this.config.queue, this.exchange, key, ); } } /** * 开始消费事件 * 可靠性要点: * 1. 手动 ACK(处理成功后确认) * 2. 幂等处理(通过 eventId 去重) * 3. 重试机制(通过 header 计数) * 4. 死信队列(超过重试次数的消息) */ async consume( handler: (event: DomainEvent) => Promise<void>, isProcessed: (eventId: string) => Promise<boolean>, ): Promise<void> { if (!this.channel) throw new Error('Consumer not connected'); await this.channel.consume(this.config.queue, async (msg) => { if (!msg) return; try { const event: DomainEvent = JSON.parse(msg.content.toString()); // 幂等检查:跳过已处理的事件 if (await isProcessed(event.eventId)) { this.channel!.ack(msg); return; } // 处理事件 await handler(event); // 处理成功:确认消息 this.channel!.ack(msg); } catch (error) { // 检查重试次数 const retryCount = (msg.properties.headers?.['x-retry-count'] ?? 0) as number; if (retryCount >= this.config.maxRetries) { // 超过重试次数:发送到死信队列 this.channel!.nack(msg, false, false); } else { // 重试:重新发布消息(带递增的重试计数) const delay = Math.min(1000 * Math.pow(2, retryCount), 30000); setTimeout(() => { this.channel!.publish(this.exchange, msg.fields.routingKey, msg.content, { ...msg.properties, headers: { ...msg.properties.headers, 'x-retry-count': retryCount + 1, }, }); this.channel!.ack(msg); }, delay); } } }); } }

2.5 REST vs gRPC vs 消息队列:AI 生成代码质量对比

维度RESTgRPC消息队列
AI 生成准确度⭐⭐⭐⭐⭐ 极高⭐⭐⭐⭐ 高⭐⭐⭐ 中
AI 常见错误缺少重试/超时Protobuf 语法错误幂等性遗漏
人工审查重点错误处理、超时流式处理、deadline消息顺序、去重
测试难度⭐⭐ 低⭐⭐⭐ 中⭐⭐⭐⭐ 高
调试难度⭐⭐ 低⭐⭐⭐ 中⭐⭐⭐⭐ 高

3. Serverless 函数 AI 生成

3.1 Serverless 平台对比

平台运行时支持冷启动最大执行时间最大包大小价格适用场景
AWS LambdaNode.js, Python, Go, Java, Rust, .NET, Ruby100ms-10s(取决于运行时和包大小)15 分钟250MB(解压后)免费(100 万次/月)/ $0.20/百万次通用 Serverless、AWS 生态
Vercel FunctionsNode.js, Python, Go, Ruby50-200ms60s(Hobby)/ 300s(Pro)50MB免费(100GB 带宽)/ $20/月(Pro)Next.js API Routes、前端配套
Cloudflare WorkersJavaScript/TypeScript, Rust (WASM)< 5ms(V8 Isolate)30s(免费)/ 15min(付费)10MB(免费)/ 25MB(付费)免费(10 万次/天)/ $5/月(1000 万次)边缘计算、低延迟 API
Deno DeployTypeScript/JavaScript< 10ms无限制(流式)无限制免费(10 万次/天)/ $20/月(Pro)TypeScript 优先、边缘部署
Supabase Edge FunctionsTypeScript (Deno)< 100ms150s20MB免费(50 万次/月)/ $25/月(Pro)Supabase 生态、数据库触发
Netlify FunctionsNode.js, Go100-500ms10s(免费)/ 26s(Pro)50MB免费(12.5 万次/月)/ $19/月(Pro)Jamstack 配套
Google Cloud FunctionsNode.js, Python, Go, Java, .NET, Ruby, PHP100ms-5s9 分钟(v1)/ 60 分钟(v2)500MB(解压后)免费(200 万次/月)/ $0.40/百万次GCP 生态、事件驱动
Azure FunctionsNode.js, Python, Java, C#, PowerShell100ms-5s5-10 分钟无限制免费(100 万次/月)/ $0.20/百万次Azure 生态、企业应用
Serverless 平台选择决策树: 你的主要需求是什么? ├── 极低延迟(< 10ms 冷启动) │ └── Cloudflare Workers / Deno Deploy │ 适合:边缘 API、A/B 测试、地理路由 ├── Next.js / 前端配套 │ └── Vercel Functions │ 适合:API Routes、ISR、Middleware ├── AWS 生态集成 │ └── AWS Lambda │ 适合:S3 触发、DynamoDB 流、SQS 消费 ├── 数据库触发 / Supabase 生态 │ └── Supabase Edge Functions │ 适合:数据库 Webhook、RLS 辅助逻辑 └── 长时间运行任务 └── AWS Lambda(15min)/ GCF v2(60min) 适合:数据处理、报告生成、批量操作

3.2 操作步骤:AI 生成 Serverless 函数

步骤 1:定义函数需求

提示词模板:生成 Serverless 函数

你是一位 Serverless 架构专家。请为以下需求生成 Serverless 函数代码。 ## 函数需求 - 功能描述:[描述函数的业务逻辑] - 触发方式:[HTTP / 定时 / 事件(S3/SQS/DynamoDB Stream)] - 输入:[请求格式或事件格式] - 输出:[响应格式] ## 目标平台 - 平台:[AWS Lambda / Vercel / Cloudflare Workers / Supabase Edge] - 运行时:[Node.js 20 / Python 3.12 / Go 1.22 / Rust] - 框架:[SST / Serverless Framework / 原生 / Hono] ## 性能要求 - 冷启动目标:[例如 < 200ms] - 执行时间目标:[例如 < 3s] - 内存配置:[例如 256MB] ## 必须包含 1. 输入验证(使用 [Zod / Pydantic]) 2. 错误处理(统一错误响应格式) 3. 日志记录(结构化 JSON 日志) 4. 环境变量配置(不硬编码密钥) 5. 冷启动优化(连接复用、延迟初始化) 6. CORS 配置(如果是 HTTP 触发) 7. 部署配置文件 ## 冷启动优化要求 - 数据库连接在 handler 外部初始化(连接复用) - 最小化依赖包大小 - 使用 tree-shaking 和 bundling - 避免在初始化阶段做不必要的 I/O

步骤 2:AWS Lambda 函数示例

// ============================================ // functions/process-order.ts —— AWS Lambda 订单处理函数 // 使用 SST (Serverless Stack) 框架 // ============================================ import { APIGatewayProxyHandlerV2 } from 'aws-lambda'; import { z } from 'zod'; // ---- 冷启动优化:在 handler 外部初始化 ---- // 数据库连接在 Lambda 容器生命周期内复用 import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient({ // Lambda 优化:减少连接池大小 datasources: { db: { url: process.env.DATABASE_URL }, }, }); // ---- 输入验证 Schema ---- const CreateOrderSchema = z.object({ customerId: z.string().uuid(), items: z.array(z.object({ productId: z.string().uuid(), quantity: z.number().int().positive().max(100), })).min(1).max(50), shippingAddress: z.object({ street: z.string().min(1).max(200), city: z.string().min(1).max(100), zipCode: z.string().regex(/^\d{5,6}$/), country: z.string().length(2), // ISO 3166-1 alpha-2 }), }); // ---- Lambda Handler ---- export const handler: APIGatewayProxyHandlerV2 = async (event) => { const requestId = event.requestContext?.requestId ?? 'unknown'; try { // 1. 解析和验证输入 const body = JSON.parse(event.body ?? '{}'); const input = CreateOrderSchema.parse(body); // 2. 业务逻辑 const order = await prisma.$transaction(async (tx) => { // 检查库存 for (const item of input.items) { const product = await tx.product.findUnique({ where: { id: item.productId }, }); if (!product || product.stock < item.quantity) { throw new BusinessError( 'INSUFFICIENT_STOCK', `商品 ${item.productId} 库存不足`, ); } } // 创建订单 const order = await tx.order.create({ data: { customerId: input.customerId, status: 'PENDING', items: { create: input.items.map(item => ({ productId: item.productId, quantity: item.quantity, })), }, shippingAddress: input.shippingAddress, }, include: { items: true }, }); // 扣减库存 for (const item of input.items) { await tx.product.update({ where: { id: item.productId }, data: { stock: { decrement: item.quantity } }, }); } return order; }); // 3. 结构化日志 console.log(JSON.stringify({ level: 'info', message: 'Order created', requestId, orderId: order.id, customerId: input.customerId, itemCount: input.items.length, })); // 4. 返回响应 return { statusCode: 201, headers: { 'Content-Type': 'application/json', 'X-Request-Id': requestId, }, body: JSON.stringify({ orderId: order.id, status: order.status, createdAt: order.createdAt, }), }; } catch (error) { // 统一错误处理 if (error instanceof z.ZodError) { return { statusCode: 400, body: JSON.stringify({ error: 'VALIDATION_ERROR', details: error.errors, }), }; } if (error instanceof BusinessError) { return { statusCode: 422, body: JSON.stringify({ error: error.code, message: error.message, }), }; } // 未知错误:记录日志但不暴露内部信息 console.error(JSON.stringify({ level: 'error', message: 'Unhandled error', requestId, error: error instanceof Error ? error.message : 'Unknown', stack: error instanceof Error ? error.stack : undefined, })); return { statusCode: 500, body: JSON.stringify({ error: 'INTERNAL_ERROR', message: '服务器内部错误', requestId, }), }; } }; class BusinessError extends Error { constructor( public readonly code: string, message: string, ) { super(message); this.name = 'BusinessError'; } }

步骤 3:Cloudflare Workers 函数示例

// ============================================ // src/worker.ts —— Cloudflare Workers API // 使用 Hono 框架(轻量级,适合 Workers) // ============================================ import { Hono } from 'hono'; import { cors } from 'hono/cors'; import { zValidator } from '@hono/zod-validator'; import { z } from 'zod'; // Cloudflare Workers 环境绑定类型 type Bindings = { DB: D1Database; // Cloudflare D1 数据库 KV: KVNamespace; // Cloudflare KV 存储 RATE_LIMITER: RateLimit; // 速率限制 API_KEY: string; // 环境变量 }; const app = new Hono<{ Bindings: Bindings }>(); // 中间件 app.use('*', cors({ origin: ['https://yourdomain.com'], allowMethods: ['GET', 'POST', 'PUT', 'DELETE'], })); // 速率限制中间件 app.use('/api/*', async (c, next) => { const ip = c.req.header('CF-Connecting-IP') ?? 'unknown'; const { success } = await c.env.RATE_LIMITER.limit({ key: ip, }); if (!success) { return c.json({ error: 'RATE_LIMITED' }, 429); } await next(); }); // ---- API 端点 ---- const ProductSchema = z.object({ name: z.string().min(1).max(200), price: z.number().positive(), category: z.string().min(1), }); // 创建产品 app.post( '/api/products', zValidator('json', ProductSchema), async (c) => { const input = c.req.valid('json'); // 使用 Cloudflare D1(SQLite 边缘数据库) const result = await c.env.DB.prepare( 'INSERT INTO products (name, price, category) VALUES (?, ?, ?) RETURNING *' ) .bind(input.name, input.price, input.category) .first(); // 缓存失效 await c.env.KV.delete('products:list'); return c.json(result, 201); }, ); // 获取产品列表(带 KV 缓存) app.get('/api/products', async (c) => { // 先查 KV 缓存 const cached = await c.env.KV.get('products:list', 'json'); if (cached) { return c.json(cached); } // 缓存未命中:查数据库 const { results } = await c.env.DB.prepare( 'SELECT * FROM products ORDER BY created_at DESC LIMIT 100' ).all(); // 写入缓存(TTL 60 秒) await c.env.KV.put('products:list', JSON.stringify(results), { expirationTtl: 60, }); return c.json(results); }); export default app;

步骤 4:Vercel Serverless Function 示例

// ============================================ // app/api/webhooks/stripe/route.ts // Next.js App Router + Vercel Serverless Function // Stripe Webhook 处理 // ============================================ import { NextRequest, NextResponse } from 'next/server'; import Stripe from 'stripe'; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: '2024-12-18.acacia', }); const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!; export async function POST(request: NextRequest) { const body = await request.text(); const signature = request.headers.get('stripe-signature')!; let event: Stripe.Event; try { // 验证 Webhook 签名(防止伪造) event = stripe.webhooks.constructEvent(body, signature, webhookSecret); } catch (err) { console.error('Webhook signature verification failed'); return NextResponse.json( { error: 'Invalid signature' }, { status: 400 }, ); } // 幂等处理:检查事件是否已处理 const processed = await checkEventProcessed(event.id); if (processed) { return NextResponse.json({ received: true }); } try { switch (event.type) { case 'checkout.session.completed': { const session = event.data.object as Stripe.Checkout.Session; await handleCheckoutComplete(session); break; } case 'invoice.payment_succeeded': { const invoice = event.data.object as Stripe.Invoice; await handlePaymentSucceeded(invoice); break; } case 'customer.subscription.deleted': { const subscription = event.data.object as Stripe.Subscription; await handleSubscriptionCanceled(subscription); break; } default: console.log(`Unhandled event type: ${event.type}`); } // 标记事件已处理 await markEventProcessed(event.id); return NextResponse.json({ received: true }); } catch (error) { console.error(`Error processing ${event.type}:`, error); // 返回 500 让 Stripe 重试 return NextResponse.json( { error: 'Processing failed' }, { status: 500 }, ); } } // Vercel 配置:增加 body 大小限制 export const config = { api: { bodyParser: false, // Stripe 需要原始 body 验证签名 }, };

3.3 Serverless 冷启动优化策略

冷启动是 Serverless 最大的性能挑战。AI 生成的代码经常忽略冷启动优化。

冷启动优化清单: ┌─────────────────────────────────────────────────────────────┐ │ Serverless 冷启动优化策略 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 1. 代码层优化 │ │ ├── 最小化依赖包大小(tree-shaking + bundling) │ │ ├── 使用 esbuild/swc 替代 webpack(构建更快) │ │ ├── 延迟加载非关键模块(dynamic import) │ │ ├── 避免在初始化阶段做 I/O 操作 │ │ └── 使用轻量级库(如 Hono 替代 Express) │ │ │ │ 2. 连接层优化 │ │ ├── 数据库连接在 handler 外部初始化(连接复用) │ │ ├── 使用连接池代理(如 PgBouncer、RDS Proxy) │ │ ├── HTTP 客户端使用 keep-alive │ │ └── 缓存 SDK 客户端实例 │ │ │ │ 3. 平台层优化 │ │ ├── AWS Lambda:使用 SnapStart(Java)或 Provisioned │ │ │ Concurrency(关键路径) │ │ ├── AWS Lambda:选择 ARM64 架构(Graviton2,性价比更高) │ │ ├── Cloudflare Workers:天然低冷启动(V8 Isolate) │ │ └── Vercel:使用 Edge Runtime(< 50ms 冷启动) │ │ │ │ 4. 架构层优化 │ │ ├── 预热策略:定时触发保持实例活跃 │ │ ├── 异步处理:将耗时操作推到队列 │ │ ├── 响应流式化:先返回头部,再流式返回 body │ │ └── 边缘缓存:使用 CDN 缓存减少函数调用 │ │ │ │ 各平台冷启动时间参考(2025): │ │ • Cloudflare Workers:< 5ms(V8 Isolate,无冷启动问题) │ │ • Deno Deploy:< 10ms │ │ • Vercel Edge:< 50ms │ │ • AWS Lambda (Node.js):100-300ms(首次) │ │ • AWS Lambda (Python):200-500ms(首次) │ │ • AWS Lambda (Java):1-10s(首次,SnapStart 可降至 200ms) │ │ • AWS Lambda (Go/Rust):< 100ms(编译型语言优势) │ │ │ └─────────────────────────────────────────────────────────────┘

提示词模板:审查 Serverless 函数冷启动性能

你是一位 Serverless 性能优化专家。请审查以下 Serverless 函数代码,识别冷启动性能问题。 ## 代码 [粘贴你的 Serverless 函数代码] ## 目标平台 [AWS Lambda / Cloudflare Workers / Vercel] ## 审查清单 1. **初始化阶段**:handler 外部是否有不必要的 I/O 操作? 2. **依赖大小**:是否引入了不必要的大型依赖?能否用轻量替代? 3. **连接管理**:数据库/HTTP 连接是否在 handler 外部初始化并复用? 4. **延迟加载**:非关键模块是否使用了 dynamic import? 5. **包大小**:部署包大小是否超过推荐值?是否使用了 bundling? 6. **运行时选择**:是否选择了最适合冷启动的运行时? 7. **内存配置**:内存是否配置合理?(Lambda 中更多内存 = 更多 CPU = 更快初始化) ## 输出格式 对每个问题标注影响程度(🔴 严重 / 🟡 中等 / 🟢 轻微),并给出优化建议和预期改善。

4. 部署配置 AI 生成

4.1 Docker 配置生成

Docker 是微服务部署的标准容器化方案。AI 对 Dockerfile 生成的质量较高,但多阶段构建和安全加固经常被忽略。

提示词模板:生成优化的 Dockerfile

你是一位 Docker 和容器化专家。请为以下微服务生成生产级 Dockerfile。 ## 服务信息 - 语言/框架:[例如 TypeScript + NestJS / Go + Gin / Python + FastAPI] - 包管理器:[npm / pnpm / yarn / pip / go mod] - 构建工具:[esbuild / swc / webpack / none] - 需要的系统依赖:[例如 sharp 需要 libvips] ## 要求 1. 多阶段构建(builder → runner) 2. 使用 Alpine 或 Distroless 基础镜像(最小化攻击面) 3. 非 root 用户运行(安全加固) 4. 健康检查(HEALTHCHECK 指令) 5. 合理的 .dockerignore 6. 依赖缓存优化(利用 Docker 层缓存) 7. 最终镜像大小目标:< [例如 100MB] 8. 包含 docker-compose.yml(开发环境) ## 安全要求 - 不在镜像中包含 .env 文件或密钥 - 使用固定版本的基础镜像(不用 latest) - 最小化安装的包(不安装开发依赖) - 设置只读文件系统(如果可能)

生产级 Dockerfile 示例(TypeScript + NestJS)

# ============================================ # Dockerfile —— NestJS 微服务(多阶段构建) # 最终镜像大小目标:< 150MB # ============================================ # ---- 阶段 1:依赖安装 ---- FROM node:20-alpine AS deps WORKDIR /app # 只复制依赖文件(利用 Docker 层缓存) COPY package.json pnpm-lock.yaml ./ RUN corepack enable pnpm && pnpm install --frozen-lockfile --prod # ---- 阶段 2:构建 ---- FROM node:20-alpine AS builder WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN corepack enable pnpm && pnpm install --frozen-lockfile COPY . . RUN pnpm build # ---- 阶段 3:生产运行 ---- FROM node:20-alpine AS runner WORKDIR /app # 安全加固:创建非 root 用户 RUN addgroup --system --gid 1001 appgroup && \ adduser --system --uid 1001 appuser # 只复制生产依赖和构建产物 COPY --from=deps /app/node_modules ./node_modules COPY --from=builder /app/dist ./dist COPY --from=builder /app/package.json ./ # 设置文件权限 RUN chown -R appuser:appgroup /app # 切换到非 root 用户 USER appuser # 环境变量 ENV NODE_ENV=production ENV PORT=3000 # 暴露端口 EXPOSE 3000 # 健康检查 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1 # 启动命令 CMD ["node", "dist/main.js"]

docker-compose.yml 示例(微服务开发环境)

# ============================================ # docker-compose.yml —— 微服务本地开发环境 # ============================================ version: '3.8' services: # ---- API 网关 ---- api-gateway: build: context: ./services/api-gateway dockerfile: Dockerfile.dev ports: - "3000:3000" environment: - NODE_ENV=development - ORDER_SERVICE_URL=http://order-service:3001 - INVENTORY_SERVICE_URL=http://inventory-service:3002 - USER_SERVICE_URL=http://user-service:3003 depends_on: - order-service - inventory-service - user-service networks: - microservices # ---- 订单服务 ---- order-service: build: context: ./services/order-service dockerfile: Dockerfile.dev ports: - "3001:3001" environment: - NODE_ENV=development - DATABASE_URL=postgresql://postgres:postgres@order-db:5432/orders - RABBITMQ_URL=amqp://rabbitmq:5672 depends_on: order-db: condition: service_healthy rabbitmq: condition: service_healthy networks: - microservices # ---- 库存服务 ---- inventory-service: build: context: ./services/inventory-service dockerfile: Dockerfile.dev ports: - "3002:3002" environment: - NODE_ENV=development - DATABASE_URL=postgresql://postgres:postgres@inventory-db:5432/inventory - RABBITMQ_URL=amqp://rabbitmq:5672 depends_on: inventory-db: condition: service_healthy rabbitmq: condition: service_healthy networks: - microservices # ---- 用户服务 ---- user-service: build: context: ./services/user-service dockerfile: Dockerfile.dev ports: - "3003:3003" environment: - NODE_ENV=development - DATABASE_URL=postgresql://postgres:postgres@user-db:5432/users - REDIS_URL=redis://redis:6379 depends_on: user-db: condition: service_healthy redis: condition: service_healthy networks: - microservices # ---- 数据库(每个服务独立数据库) ---- order-db: image: postgres:16-alpine environment: POSTGRES_DB: orders POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres volumes: - order-db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 networks: - microservices inventory-db: image: postgres:16-alpine environment: POSTGRES_DB: inventory POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres volumes: - inventory-db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 networks: - microservices user-db: image: postgres:16-alpine environment: POSTGRES_DB: users POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres volumes: - user-db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 networks: - microservices # ---- 基础设施 ---- rabbitmq: image: rabbitmq:3.13-management-alpine ports: - "5672:5672" - "15672:15672" # 管理 UI healthcheck: test: ["CMD", "rabbitmq-diagnostics", "check_running"] interval: 10s timeout: 5s retries: 5 networks: - microservices redis: image: redis:7-alpine ports: - "6379:6379" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 5 networks: - microservices volumes: order-db-data: inventory-db-data: user-db-data: networks: microservices: driver: bridge

4.2 Kubernetes 部署配置生成

对于需要编排多个微服务的场景,Kubernetes 是事实标准。AI 可以生成 K8s manifest,但资源限制、HPA 配置和网络策略需要人工调优。

提示词模板:生成 Kubernetes 部署配置

你是一位 Kubernetes 运维专家。请为以下微服务生成生产级 K8s 部署配置。 ## 服务信息 - 服务名称:[服务名] - 容器镜像:[镜像地址:标签] - 端口:[HTTP 端口] / [gRPC 端口(如有)] - 健康检查端点:[例如 /health] - 就绪检查端点:[例如 /ready] ## 资源需求 - CPU 请求/限制:[例如 100m / 500m] - 内存请求/限制:[例如 128Mi / 512Mi] - 副本数:[最小/最大] ## 要求 1. Deployment(包含滚动更新策略) 2. Service(ClusterIP + 可选 LoadBalancer) 3. HPA(水平自动扩缩容) 4. ConfigMap(非敏感配置) 5. Secret(敏感配置,使用 External Secrets Operator) 6. NetworkPolicy(限制服务间通信) 7. PodDisruptionBudget(保证可用性) 8. ServiceAccount(最小权限) ## 安全要求 - Pod 以非 root 用户运行 - 只读根文件系统 - 禁止特权容器 - 限制 Linux capabilities

Kubernetes Deployment 示例

# ============================================ # k8s/order-service/deployment.yaml # 订单服务 Kubernetes 部署配置 # ============================================ apiVersion: apps/v1 kind: Deployment metadata: name: order-service namespace: production labels: app: order-service version: v1 spec: replicas: 3 selector: matchLabels: app: order-service strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 # 滚动更新时最多多 1 个 Pod maxUnavailable: 0 # 滚动更新时不允许不可用 template: metadata: labels: app: order-service version: v1 annotations: prometheus.io/scrape: "true" prometheus.io/port: "3001" prometheus.io/path: "/metrics" spec: serviceAccountName: order-service # 安全上下文 securityContext: runAsNonRoot: true runAsUser: 1001 runAsGroup: 1001 fsGroup: 1001 containers: - name: order-service image: myregistry/order-service:v1.2.3 ports: - name: http containerPort: 3001 protocol: TCP # 环境变量 env: - name: NODE_ENV value: "production" - name: PORT value: "3001" - name: DATABASE_URL valueFrom: secretKeyRef: name: order-service-secrets key: database-url - name: RABBITMQ_URL valueFrom: secretKeyRef: name: order-service-secrets key: rabbitmq-url # 资源限制 resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 512Mi # 存活探针 livenessProbe: httpGet: path: /health port: http initialDelaySeconds: 15 periodSeconds: 20 timeoutSeconds: 5 failureThreshold: 3 # 就绪探针 readinessProbe: httpGet: path: /ready port: http initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 # 启动探针(慢启动保护) startupProbe: httpGet: path: /health port: http initialDelaySeconds: 5 periodSeconds: 5 failureThreshold: 30 # 容器安全上下文 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL # 临时目录(只读根文件系统需要) volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: {} # Pod 反亲和性(分散到不同节点) affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - order-service topologyKey: kubernetes.io/hostname --- # Service apiVersion: v1 kind: Service metadata: name: order-service namespace: production spec: selector: app: order-service ports: - name: http port: 80 targetPort: http protocol: TCP type: ClusterIP --- # HPA(水平自动扩缩容) apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: order-service namespace: production spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: order-service minReplicas: 3 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 - type: Resource resource: name: memory target: type: Utilization averageUtilization: 80 behavior: scaleUp: stabilizationWindowSeconds: 60 policies: - type: Pods value: 2 periodSeconds: 60 scaleDown: stabilizationWindowSeconds: 300 policies: - type: Pods value: 1 periodSeconds: 120 --- # PodDisruptionBudget(保证可用性) apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: order-service namespace: production spec: minAvailable: 2 selector: matchLabels: app: order-service --- # NetworkPolicy(限制网络访问) apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: order-service namespace: production spec: podSelector: matchLabels: app: order-service policyTypes: - Ingress - Egress ingress: # 只允许 API 网关访问 - from: - podSelector: matchLabels: app: api-gateway ports: - protocol: TCP port: 3001 egress: # 允许访问数据库 - to: - podSelector: matchLabels: app: order-db ports: - protocol: TCP port: 5432 # 允许访问 RabbitMQ - to: - podSelector: matchLabels: app: rabbitmq ports: - protocol: TCP port: 5672 # 允许 DNS 查询 - to: [] ports: - protocol: UDP port: 53 - protocol: TCP port: 53

5. API 网关配置

5.1 API 网关在微服务中的角色

API 网关是微服务架构的”前门”,负责路由、认证、限流、监控等横切关注点。

API 网关架构: ┌─────────────────────────────────────────────────────────────┐ │ 客户端 │ │ (Web / Mobile / 第三方) │ └──────────────────────┬──────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ API 网关 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 认证/授权 │ │ 速率限制 │ │ 请求路由 │ │ 负载均衡 │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 请求转换 │ │ 响应缓存 │ │ 断路器 │ │ 日志/监控 │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ │ │ │ CORS │ │ API 版本 │ │ │ └──────────┘ └──────────┘ │ └──────┬──────────────┬──────────────┬────────────────────────┘ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 用户服务 │ │ 订单服务 │ │ 库存服务 │ │ :3001 │ │ :3002 │ │ :3003 │ └──────────┘ └──────────┘ └──────────┘

5.2 API 网关工具对比

网关类型核心优势配置方式价格适用场景
Kong通用 API 网关插件生态丰富、声明式配置、多协议YAML / Admin API免费(开源)/ 联系销售大型微服务、企业级
Traefik云原生反向代理自动服务发现、Let’s Encrypt、Docker/K8s 原生YAML / Docker Labels免费(开源)/ 联系销售容器化微服务
APISIX高性能 API 网关极高性能、插件化、DashboardYAML / Admin API免费(开源)高性能需求
Nginx反向代理成熟稳定、高性能、广泛使用nginx.conf免费(开源)/ 联系销售简单路由、静态配置
AWS API Gateway托管服务与 Lambda 深度集成、WebSocket、REST/HTTPConsole / CloudFormation$1/百万次 + 数据传输AWS 生态
Cloudflare Gateway边缘网关全球边缘网络、DDoS 防护、Workers 集成Dashboard / API按用量计费边缘路由、安全防护
Express GatewayNode.js 网关JavaScript 生态、Express 中间件兼容YAML / JS免费(开源)Node.js 微服务

5.3 操作步骤:AI 生成 API 网关配置

提示词模板:生成 API 网关配置

你是一位 API 网关配置专家。请为以下微服务架构生成 API 网关配置。 ## 微服务列表 [列出所有微服务及其端点] ## 网关选型 - 网关:[Kong / Traefik / APISIX / Nginx] - 部署方式:[Docker / Kubernetes / 托管服务] ## 路由规则 [描述 URL 路径到服务的映射关系] ## 要求 1. 路由配置(路径前缀匹配 + 服务转发) 2. 认证中间件(JWT 验证,白名单路径) 3. 速率限制(全局 + 每用户) 4. CORS 配置 5. 请求/响应日志 6. 健康检查端点 7. API 版本管理(/v1/, /v2/) 8. 超时配置(连接超时 + 读取超时) 9. 断路器配置(失败阈值 + 恢复时间) 10. SSL/TLS 终止 ## 安全要求 - 隐藏后端服务的内部端口和路径 - 移除敏感响应头(X-Powered-By 等) - 请求大小限制 - IP 白名单/黑名单(如需要)

Traefik 配置示例(Docker Compose)

# ============================================ # traefik/docker-compose.yml # Traefik API 网关配置(Docker 环境) # ============================================ version: '3.8' services: traefik: image: traefik:v3.2 command: # API 和 Dashboard - "--api.dashboard=true" - "--api.insecure=false" # Docker Provider - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--providers.docker.network=microservices" # 入口点 - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" # HTTP → HTTPS 重定向 - "--entrypoints.web.http.redirections.entrypoint.to=websecure" # Let's Encrypt 自动证书 - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true" - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" - "--certificatesresolvers.letsencrypt.acme.email=admin@yourdomain.com" - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" # 访问日志 - "--accesslog=true" - "--accesslog.format=json" # Prometheus 指标 - "--metrics.prometheus=true" ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - letsencrypt:/letsencrypt networks: - microservices labels: # Dashboard 路由 - "traefik.enable=true" - "traefik.http.routers.dashboard.rule=Host(`traefik.yourdomain.com`)" - "traefik.http.routers.dashboard.service=api@internal" - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt" # Dashboard 认证 - "traefik.http.routers.dashboard.middlewares=dashboard-auth" - "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$apr1$$..." # ---- 微服务路由配置(通过 Docker Labels) ---- order-service: image: myregistry/order-service:latest networks: - microservices labels: - "traefik.enable=true" # 路由规则 - "traefik.http.routers.orders.rule=Host(`api.yourdomain.com`) && PathPrefix(`/api/v1/orders`)" - "traefik.http.routers.orders.tls.certresolver=letsencrypt" # 中间件链 - "traefik.http.routers.orders.middlewares=rate-limit,cors,strip-prefix" # 服务端口 - "traefik.http.services.orders.loadbalancer.server.port=3001" # 健康检查 - "traefik.http.services.orders.loadbalancer.healthcheck.path=/health" - "traefik.http.services.orders.loadbalancer.healthcheck.interval=10s" inventory-service: image: myregistry/inventory-service:latest networks: - microservices labels: - "traefik.enable=true" - "traefik.http.routers.inventory.rule=Host(`api.yourdomain.com`) && PathPrefix(`/api/v1/inventory`)" - "traefik.http.routers.inventory.tls.certresolver=letsencrypt" - "traefik.http.routers.inventory.middlewares=rate-limit,cors" - "traefik.http.services.inventory.loadbalancer.server.port=3002" user-service: image: myregistry/user-service:latest networks: - microservices labels: - "traefik.enable=true" - "traefik.http.routers.users.rule=Host(`api.yourdomain.com`) && PathPrefix(`/api/v1/users`)" - "traefik.http.routers.users.tls.certresolver=letsencrypt" - "traefik.http.routers.users.middlewares=rate-limit,cors" - "traefik.http.services.users.loadbalancer.server.port=3003" # ---- 全局中间件定义 ---- # (通过 Traefik 动态配置文件或 Docker Labels) # 速率限制中间件 # traefik.http.middlewares.rate-limit.ratelimit.average=100 # traefik.http.middlewares.rate-limit.ratelimit.burst=50 # traefik.http.middlewares.rate-limit.ratelimit.period=1s # CORS 中间件 # traefik.http.middlewares.cors.headers.accesscontrolallowmethods=GET,POST,PUT,DELETE,OPTIONS # traefik.http.middlewares.cors.headers.accesscontrolalloworiginlist=https://yourdomain.com # traefik.http.middlewares.cors.headers.accesscontrolmaxage=86400 volumes: letsencrypt: networks: microservices: external: true

6. 断路器与降级策略

6.1 断路器模式详解

断路器(Circuit Breaker)是微服务弹性设计的核心模式,防止一个服务的故障级联到整个系统。

断路器状态机: ┌──────────┐ 失败次数 ≥ 阈值 ┌──────────┐ │ │ ──────────────────────→ │ │ │ CLOSED │ │ OPEN │ │ (正常) │ ←────────────────────── │ (熔断) │ │ │ 半开状态测试成功 │ │ └──────────┘ └────┬─────┘ ↑ │ │ 超过恢复时间 │ │ ┌──────────┐ │ └──────── │HALF-OPEN │ ←─────────────┘ 测试成功 │(半开) │ └──────────┘ │ 测试失败 └──────→ 回到 OPEN 状态说明: • CLOSED(关闭):正常状态,请求正常转发 - 记录失败次数 - 失败次数达到阈值 → 切换到 OPEN • OPEN(打开/熔断):拒绝所有请求,快速失败 - 返回降级响应(缓存数据/默认值/错误提示) - 等待恢复时间 • HALF-OPEN(半开):允许少量请求测试 - 如果测试请求成功 → 切换到 CLOSED - 如果测试请求失败 → 切换回 OPEN

6.2 断路器实现

// ============================================ // resilience/circuit-breaker.ts // 通用断路器实现 // ============================================ enum CircuitState { CLOSED = 'CLOSED', OPEN = 'OPEN', HALF_OPEN = 'HALF_OPEN', } interface CircuitBreakerConfig { failureThreshold: number; // 失败阈值(触发熔断) successThreshold: number; // 成功阈值(恢复正常) timeout: number; // 熔断恢复时间(ms) monitorInterval: number; // 监控窗口(ms) } interface CircuitBreakerMetrics { state: CircuitState; failures: number; successes: number; lastFailureTime: number; totalRequests: number; totalFailures: number; } class CircuitBreaker { private state: CircuitState = CircuitState.CLOSED; private failures = 0; private successes = 0; private lastFailureTime = 0; private totalRequests = 0; private totalFailures = 0; constructor( private readonly name: string, private readonly config: CircuitBreakerConfig, ) {} /** * 通过断路器执行操作 * @param action 要执行的异步操作 * @param fallback 降级函数(断路器打开时调用) */ async execute<T>( action: () => Promise<T>, fallback?: () => Promise<T>, ): Promise<T> { this.totalRequests++; // 检查断路器状态 if (this.state === CircuitState.OPEN) { // 检查是否可以进入半开状态 if (Date.now() - this.lastFailureTime >= this.config.timeout) { this.state = CircuitState.HALF_OPEN; this.successes = 0; } else { // 断路器打开:执行降级 if (fallback) { return fallback(); } throw new CircuitBreakerOpenError(this.name); } } try { const result = await action(); this.onSuccess(); return result; } catch (error) { this.onFailure(); if (this.state === CircuitState.OPEN && fallback) { return fallback(); } throw error; } } private onSuccess(): void { if (this.state === CircuitState.HALF_OPEN) { this.successes++; if (this.successes >= this.config.successThreshold) { // 恢复正常 this.state = CircuitState.CLOSED; this.failures = 0; this.successes = 0; console.log(`[CircuitBreaker:${this.name}] 恢复正常 (CLOSED)`); } } else { this.failures = 0; // 重置连续失败计数 } } private onFailure(): void { this.failures++; this.totalFailures++; this.lastFailureTime = Date.now(); if (this.state === CircuitState.HALF_OPEN) { // 半开状态下失败:回到打开状态 this.state = CircuitState.OPEN; console.log(`[CircuitBreaker:${this.name}] 半开测试失败,重新熔断 (OPEN)`); } else if (this.failures >= this.config.failureThreshold) { // 达到失败阈值:打开断路器 this.state = CircuitState.OPEN; console.log(`[CircuitBreaker:${this.name}] 触发熔断 (OPEN),连续失败 ${this.failures} 次`); } } getMetrics(): CircuitBreakerMetrics { return { state: this.state, failures: this.failures, successes: this.successes, lastFailureTime: this.lastFailureTime, totalRequests: this.totalRequests, totalFailures: this.totalFailures, }; } } class CircuitBreakerOpenError extends Error { constructor(serviceName: string) { super(`断路器已打开:${serviceName} 服务暂时不可用`); this.name = 'CircuitBreakerOpenError'; } }

6.3 降级策略模式

// ============================================ // resilience/fallback-strategies.ts // 常见降级策略 // ============================================ // 策略 1:缓存降级(返回缓存的旧数据) class CacheFallback<T> { private cache: Map<string, { data: T; timestamp: number }> = new Map(); constructor(private readonly ttl: number = 300_000) {} // 默认 5 分钟 set(key: string, data: T): void { this.cache.set(key, { data, timestamp: Date.now() }); } get(key: string): T | null { const entry = this.cache.get(key); if (!entry) return null; if (Date.now() - entry.timestamp > this.ttl) { this.cache.delete(key); return null; } return entry.data; } } // 策略 2:默认值降级 function defaultFallback<T>(defaultValue: T): () => Promise<T> { return async () => defaultValue; } // 策略 3:部分降级(返回部分数据) async function partialFallback( services: Array<{ name: string; call: () => Promise<any> }>, ): Promise<Record<string, any>> { const results: Record<string, any> = {}; await Promise.allSettled( services.map(async (service) => { try { results[service.name] = await service.call(); } catch { results[service.name] = null; // 失败的服务返回 null } }), ); return results; } // ---- 使用示例 ---- const inventoryBreaker = new CircuitBreaker('inventory-service', { failureThreshold: 5, // 连续 5 次失败触发熔断 successThreshold: 3, // 连续 3 次成功恢复 timeout: 30_000, // 30 秒后尝试恢复 monitorInterval: 60_000, // 60 秒监控窗口 }); const inventoryCache = new CacheFallback<InventoryCheckResponse>(); async function checkInventoryWithResilience( productId: string, quantity: number, traceId: string, ): Promise<InventoryCheckResponse> { return inventoryBreaker.execute( // 正常调用 async () => { const result = await inventoryClient.checkAvailability( { productId, quantity }, traceId, ); // 成功时更新缓存 inventoryCache.set(productId, result); return result; }, // 降级策略:返回缓存数据 async () => { const cached = inventoryCache.get(productId); if (cached) { console.warn(`[Fallback] 使用缓存的库存数据: ${productId}`); return { ...cached, _fromCache: true }; } // 缓存也没有:返回保守的默认值 console.warn(`[Fallback] 无缓存,返回默认值: ${productId}`); return { available: false, currentStock: 0, _fromCache: true, _fallback: true, }; }, ); }

6.4 弹性设计模式总结

模式用途实现复杂度AI 生成质量
断路器防止级联故障⭐⭐⭐ 中⭐⭐⭐ 中
重试 + 指数退避处理瞬时故障⭐⭐ 低⭐⭐⭐⭐ 高
超时防止无限等待⭐ 低⭐⭐⭐⭐⭐ 极高
舱壁隔离限制资源消耗⭐⭐⭐ 中⭐⭐⭐ 中
缓存降级服务不可用时返回旧数据⭐⭐ 低⭐⭐⭐⭐ 高
限流防止过载⭐⭐ 低⭐⭐⭐⭐ 高
Saga 模式分布式事务⭐⭐⭐⭐⭐ 极高⭐⭐ 低
幂等性安全重试⭐⭐⭐ 中⭐⭐⭐ 中

实战案例:AI 辅助构建电商微服务系统

案例背景

一个中型电商平台需要从单体架构迁移到微服务架构,同时将部分功能迁移到 Serverless。团队规模 8 人,技术栈为 TypeScript + NestJS + PostgreSQL。

步骤 1:用 AI 分析领域并定义服务边界

向 Claude Code 提供业务描述,AI 分析后建议以下 Bounded Context:

电商平台领域分析结果: ┌─────────────────────────────────────────────────────────────┐ │ 电商平台领域模型 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 核心域(Core Domain)—— 竞争优势所在 │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ 订单上下文 │ │ 商品目录上下文 │ │ │ │ Order │ │ Catalog │ │ │ │ ├─ Order │ │ ├─ Product │ │ │ │ ├─ OrderItem │ │ ├─ Category │ │ │ │ └─ Shipment │ │ └─ Variant │ │ │ └──────────────┘ └──────────────┘ │ │ │ │ 支撑域(Supporting Domain)—— 支持核心业务 │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ 库存上下文 │ │ 支付上下文 │ │ 物流上下文 │ │ │ │ Inventory │ │ Payment │ │ Shipping │ │ │ │ ├─ Stock │ │ ├─ Payment │ │ ├─ Shipment │ │ │ │ └─ Reservation│ │ └─ Refund │ │ └─ Tracking │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ 通用域(Generic Domain)—— 可用现成方案 │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ 用户认证上下文 │ │ 通知上下文 │ │ │ │ Identity │ │ Notification │ │ │ │ → Clerk/Auth0 │ │ → Serverless │ │ │ └──────────────┘ └──────────────┘ │ │ │ │ 上下文映射(Context Map): │ │ Order ──[客户-供应商]──→ Inventory(订单需要检查库存) │ │ Order ──[客户-供应商]──→ Payment(订单需要发起支付) │ │ Order ──[发布-订阅]───→ Shipping(订单支付后触发物流) │ │ Order ──[发布-订阅]───→ Notification(订单状态变更通知用户) │ │ Catalog ──[开放主机]──→ Order(订单引用商品信息) │ │ │ └─────────────────────────────────────────────────────────────┘

人工审查决策:

AI 建议人工决策理由
拆分为 7 个微服务合并为 5 个微服务8 人团队管理 7 个服务过于分散
商品目录独立服务合并到订单服务目录变更频率低,独立服务增加复杂度
用户认证自建使用 Clerk 托管通用域不值得自建,节省开发时间
通知服务用微服务改为 Serverless 函数通知是事件驱动、低频调用,适合 Serverless
所有服务用 REST内部用 gRPC,外部用 REST内部通信需要高性能和类型安全

步骤 2:定义服务间通信契约

AI 生成 gRPC Protobuf 定义(内部通信)和 REST API Schema(外部通信):

服务通信架构: 客户端(Web/Mobile) ┌─────────────┐ │ API 网关 │ ← REST(外部) │ (Traefik) │ └──┬──┬──┬──┬─┘ │ │ │ │ ▼ ▼ ▼ ▼ ┌────┐┌────┐┌────┐┌────┐ │订单││库存││支付││物流│ ← gRPC(内部同步) │服务││服务││服务││服务│ └─┬──┘└────┘└─┬──┘└────┘ │ │ ▼ ▼ ┌─────────────────┐ │ RabbitMQ │ ← 异步事件 │ (事件总线) │ └────────┬────────┘ ┌─────────────────┐ │ 通知函数 │ ← Serverless(AWS Lambda) │ (邮件/短信/推送) │ └─────────────────┘

步骤 3:AI 生成服务骨架和部署配置

使用 Kiro Spec 驱动模式,为每个服务生成:

  • 六边形架构的项目结构
  • 领域实体和聚合根
  • gRPC 服务定义(.proto 文件)
  • REST API 端点(API 网关层)
  • Docker 配置(多阶段构建)
  • Kubernetes 部署配置
  • CI/CD 管线(GitHub Actions)

步骤 4:实现弹性通信

为关键服务间调用添加断路器和降级策略:

弹性策略配置: 订单服务 → 库存服务: 断路器:5 次失败触发,30 秒恢复 降级:返回缓存的库存数据(标记为"待确认") 重试:3 次,指数退避 订单服务 → 支付服务: 断路器:3 次失败触发,60 秒恢复 降级:不降级(支付必须成功) 重试:不重试(支付操作非幂等,使用 Saga 补偿) 订单事件 → 通知函数: 断路器:不需要(异步,消息队列自带重试) 降级:消息进入死信队列,人工处理 重试:5 次,指数退避,最终进入 DLQ

案例分析

关键决策点:

  1. 服务数量控制:AI 建议 7 个服务,人工缩减为 5 个。微服务不是越多越好,团队规模是关键约束
  2. 通用域外包:认证使用 Clerk 托管,通知使用 Serverless——通用域不值得自建微服务
  3. 混合通信:内部 gRPC + 外部 REST + 异步事件——根据场景选择最合适的通信方式
  4. 渐进式迁移:不是一次性拆分,而是先拆分核心域(订单),再逐步拆分支撑域

学习要点:

  • AI 擅长生成服务骨架和通信代码,但服务边界定义需要人工深度参与
  • 微服务的复杂度不在于单个服务,而在于服务间的通信、数据一致性和运维
  • Serverless 适合事件驱动的辅助功能(通知、数据处理),不适合核心业务逻辑
  • 断路器和降级策略是微服务的”安全气囊”,必须在设计阶段就规划好

避坑指南

❌ 常见错误

  1. 过度拆分微服务(最常见的错误)

    • 问题:AI 倾向于为每个实体创建独立服务,导致”纳米服务”泛滥。一个 5 人团队管理 15 个微服务是灾难——部署复杂度、调试难度、运维成本都会指数级增长
    • 正确做法:遵循”团队规模 = 服务数量”原则。每个服务应由 2-8 人的小团队独立维护。如果不确定是否该拆分,先用模块化单体(Modular Monolith),等到有明确的拆分理由再拆
  2. 微服务间共享数据库

    • 问题:AI 生成的微服务代码经常让多个服务访问同一个数据库,这违反了微服务的核心原则——数据所有权。共享数据库导致服务间紧耦合,一个服务的 Schema 变更会影响所有服务
    • 正确做法:每个微服务拥有自己的数据库(Database per Service)。服务间通过 API 或事件获取数据。如果需要跨服务查询,使用 CQRS 模式维护读模型
  3. 忽略 Serverless 冷启动问题

    • 问题:AI 生成的 Serverless 函数通常不考虑冷启动优化——在 handler 内部初始化数据库连接、引入大型依赖包、不使用连接池代理。这导致首次请求延迟可达数秒
    • 正确做法:数据库连接在 handler 外部初始化(连接复用)。使用 esbuild/swc 打包减小包体积。对延迟敏感的函数使用 Provisioned Concurrency 或选择 Cloudflare Workers(无冷启动)
  4. 服务间同步调用链过长

    • 问题:AI 生成的微服务通信经常形成长链式同步调用(A→B→C→D),任何一个环节超时或故障都会导致整个请求失败。延迟是累加的,可靠性是相乘的(99.9%^4 = 99.6%)
    • 正确做法:将非关键路径改为异步(消息队列)。使用断路器防止级联故障。一个请求最多同步调用 2-3 个服务,超过则需要重新审视架构
  5. 缺少断路器和降级策略

    • 问题:AI 生成的服务间调用代码通常只有基本的错误处理(try-catch),没有断路器、重试、降级等弹性机制。当下游服务故障时,上游服务会持续发送请求,加剧故障
    • 正确做法:所有服务间调用必须配置断路器(失败阈值 + 恢复时间)。关键路径必须有降级策略(缓存降级、默认值降级、部分降级)。使用指数退避重试,但只对幂等操作重试
  6. Serverless 函数中硬编码配置

    • 问题:AI 生成的 Serverless 函数经常硬编码数据库连接字符串、API Key、服务 URL 等配置。这导致代码无法在不同环境(dev/staging/prod)间复用,且存在安全风险
    • 正确做法:所有配置通过环境变量注入。敏感配置使用密钥管理服务(AWS Secrets Manager、Cloudflare Secrets)。使用 SST 或 Serverless Framework 管理环境配置
  7. 微服务间缺少分布式追踪

    • 问题:AI 生成的微服务代码通常不传递 trace-id,导致跨服务的请求无法关联。当出现问题时,无法追踪一个请求在多个服务间的完整路径
    • 正确做法:在所有服务间调用中传递 trace-id(通过 HTTP header 或 gRPC metadata)。使用 OpenTelemetry 实现分布式追踪。集成 Jaeger 或 Grafana Tempo 可视化追踪链路
  8. 忽略消息队列的幂等性

    • 问题:AI 生成的消息消费者代码通常假设消息只会被投递一次。实际上,消息队列保证的是”至少一次投递”(at-least-once),消息可能被重复投递
    • 正确做法:消费者必须实现幂等处理——使用消息 ID 去重(数据库唯一约束或 Redis SET NX)。业务操作设计为幂等的(如使用 upsert 替代 insert)

✅ 最佳实践

  1. 从模块化单体开始:新项目先用模块化单体架构,按 DDD Bounded Context 组织模块。当有明确的拆分理由(独立扩缩容、独立部署、技术异构)时再拆分为微服务

  2. 服务边界对齐团队边界:遵循康威定律——系统架构反映组织结构。每个微服务应由一个小团队(2-8 人)独立拥有和维护

  3. API 契约先行:在编写服务代码之前,先定义 API 契约(Protobuf / OpenAPI)。使用 Buf 或 Spectral 进行 API lint 和 breaking change 检测

  4. 异步优先:默认使用异步通信(消息队列),只在必须立即获得结果时使用同步调用。异步通信天然解耦,提高系统弹性

  5. 每个 Serverless 函数只做一件事:遵循单一职责原则。一个函数处理一个事件类型或一个 API 端点。避免在一个函数中塞入过多逻辑

  6. 基础设施即代码:使用 SST、Pulumi 或 Terraform 管理所有基础设施。AI 生成的 IaC 代码比手动配置更一致、更可审查

  7. 可观测性是第一优先级:在微服务架构中,可观测性(日志、指标、追踪)不是可选项。从第一天就集成 OpenTelemetry,配置结构化日志和分布式追踪

  8. 渐进式迁移:从单体到微服务的迁移应该是渐进的——先拆分变更最频繁的核心域,再逐步拆分支撑域。使用 Strangler Fig 模式逐步替换旧系统


相关资源与延伸阅读

微服务架构

  1. Microservices.io  — Chris Richardson 的微服务模式目录,涵盖服务拆分、通信、数据管理、部署等核心模式
  2. DDD 与微服务边界定义实践  — 使用 DDD Bounded Context 定义微服务边界的实战指南(2026)
  3. Buf 官方文档  — Protobuf/gRPC Schema 管理工具,支持 lint、breaking change 检测和代码生成
  4. Temporal 官方文档  — 分布式工作流引擎,适合微服务编排和 Saga 模式实现

Serverless 开发

  1. SST (Serverless Stack) 官方文档  — TypeScript 优先的 Serverless 框架,基于 AWS CDK
  2. Cloudflare Workers 官方文档  — 边缘 Serverless 平台,V8 Isolate 实现近零冷启动
  3. AWS Lambda 冷启动优化指南  — AWS 官方的 Lambda 冷启动分析和优化建议(2025)
  4. Serverless 开发模式(AI 辅助)  — AI 辅助 Serverless 开发的模式和最佳实践集合(2026)

部署与运维

  1. Pulumi — Beyond YAML: Kubernetes 2026 自动化时代  — 使用通用编程语言管理 K8s 基础设施的趋势分析(2026)
  2. Traefik 官方文档  — 云原生反向代理和 API 网关,支持 Docker/K8s 自动服务发现

参考来源


📖 返回 总览与导航 | 上一节:28d-AI辅助认证实现 | 下一节:28f-后端Steering规则与反模式

Last updated on