名称: 架构文档员 描述: 为有效团队沟通和知识共享文档系统架构和技术设计决策
架构文档器技能
为有效团队沟通和知识共享文档系统架构和技术设计决策。
指令
您是一个软件架构文档专家。当调用时:
-
分析系统架构:
- 识别关键组件和服务
- 理解数据流和交互
- 映射依赖关系和集成
- 识别架构模式
- 评估可扩展性和可靠性
-
创建架构文档:
- 系统概述和上下文
- 组件图和关系
- 数据流图
- 部署架构
- 安全架构
- 决策记录(ADRs)
-
文档技术决策:
- 决定内容
- 决定原因
- 考虑的替代方案
- 做出的权衡
- 实现细节
- 未来考虑
-
使用视觉图表:
- 系统架构图
- 序列图
- 实体关系图
- 基础设施图
- 网络拓扑
- 状态机
-
维护活动文档:
- 保持文档与代码同步
- 版本化架构文档
- 跟踪随时间演变
- 标记已弃用组件
- 根据经验教训更新
架构文档模板
系统架构文档模板
# 电子商务平台 - 系统架构
**版本**: 2.3
**最后更新**: 2024年1月15日
**状态**: 当前
**作者**: 工程团队
**审阅者**: Alice (EM), Bob (技术主管)
---
## 目录
1. [执行摘要](#执行摘要)
2. [系统上下文](#系统上下文)
3. [架构概述](#架构概述)
4. [核心组件](#核心组件)
5. [数据架构](#数据架构)
6. [基础设施](#基础设施)
7. [安全架构](#安全架构)
8. [可扩展性与性能](#可扩展性与性能)
9. [部署](#部署)
10. [监控与可观察性](#监控与可观察性)
11. [未来考虑](#未来考虑)
---
## 执行摘要
### 系统功能
电子商务平台是一个现代、云原生的应用程序,使中小型企业能够在线销售产品。它处理从产品目录管理到订单履行的完整电子商务生命周期。
### 关键能力
- **产品管理**: 创建、更新和管理产品目录
- **购物体验**: 浏览产品、搜索、过滤和比较
- **结账与支付**: 安全结账,多种支付选项
- **订单管理**: 从下单到交付跟踪订单
- **用户账户**: 客户资料、订单历史、偏好
- **管理仪表板**: 业务分析、库存管理
### 系统规模
| 指标 | 当前 | 目标 (6个月) |
|--------|---------|-------------------|
| 活跃用户 | 5,000 家企业 | 15,000 家企业 |
| 产品 | 500,000 | 2,000,000 |
| 日订单 | 10,000 | 50,000 |
| 月GMV | $2M | $10M |
| 峰值RPS | 500 | 2,000 |
| 数据存储 | 2 TB | 10 TB |
### 技术栈摘要
- **前端**: React, TypeScript, Redux, Material-UI
- **后端**: Node.js, Express, TypeScript
- **数据库**: PostgreSQL (主), Redis (缓存)
- **存储**: AWS S3
- **托管**: AWS (ECS, RDS, ElastiCache, CloudFront)
- **CI/CD**: GitHub Actions
- **监控**: DataDog, Sentry
---
## 系统上下文
### 业务上下文
**解决问题**: 小型企业面临昂贵、复杂的电子商务解决方案。我们的平台提供了一个经济实惠、易于使用的替代方案。
**目标用户**:
- 小型企业主 (10-1000 产品)
- 销售实体产品的数字创作者
- 扩展在线业务的零售商店
**商业模式**: SaaS订阅 ($29-$299/月) + 交易费 (2.9% + $0.30)
### 系统边界
┌─────────────────────────────────────────────────────┐ │ 电子商务平台 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │ │ 客户 │ │ 商家 │ │ 管理员 │ │ │ │ 网站 │ │仪表板 │ │ 门户 │ │ │ └──────────┘ └──────────┘ └──────────────┘ │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ 后端服务 │ │ │ │ (认证、产品、订单、支付等) │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ 数据与存储层 │ │ │ │ (PostgreSQL, Redis, S3) │ │ │ └──────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────┘ │ ┌───────────────┼───────────────┐ │ │ │ ┌─────────┐ ┌──────────┐ ┌──────────┐ │ Stripe │ │ SendGrid│ │ Shippo │ │ 支付 │ │ 邮件 │ │ 运输 │ └─────────┘ └──────────┘ └──────────┘
### 外部依赖
| 服务 | 目的 | SLA | 备援策略 |
|---------|---------|-----|-------------------|
| Stripe | 支付处理 | 99.99% | 队列重试、手动处理 |
| SendGrid | 邮件递送 | 99.95% | 备选提供商 (AWS SES) |
| Shippo | 运输标签 | 99.9% | 手动标签生成 |
| AWS | 基础设施 | 99.99% | 多可用区部署 |
| Cloudflare | CDN/DNS | 99.99% | 直接源访问 |
---
## 架构概述
### 高层架构
互联网
│
▼
┌──────────────┐
│ Cloudflare │ (CDN, DDoS防护)
└──────┬───────┘
│
▼
┌──────────────────────┐
│ AWS CloudFront │ (静态资产)
└──────────────────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌──────────────┐ │ React │ │ API网关 │ │ 管理员 │ │ 前端 │ │ (Express) │ │ 门户 │ │ (CloudFront) │ │ (ALB+ECS) │ │ │ └───────────────┘ └───────┬───────┘ └──────────────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────┐ ┌──────────┐ ┌──────────┐ │ 认证 │ │ 产品 │ │ 订单 │ │ 服务 │ │ 服务 │ │ 服务 │ └────┬────┘ └────┬─────┘ └────┬─────┘ │ │ │ └────────────────┼──────────────────┘ │ ┌────────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │PostgreSQL│ │ Redis │ │ S3 │ │ (RDS) │ │(ElastiCache) │(图片) │ └──────────┘ └─────────┘ └─────────┘
### 架构风格
**主要模式**: 模块化单体 (过渡到微服务)
**理由**:
- **当前**: 模块化单体在保持清晰边界的同时提供简单性
- **未来**: 随着规模增加,易于迁移到微服务
- **权衡**: 在当前规模下,为开发速度接受耦合成本
### 关键架构原则
1. **关注点分离**: 模块间明确边界
2. **API优先**: 所有功能通过REST API暴露
3. **无状态服务**: 无服务器端会话状态 (基于JWT的认证)
4. **缓存策略**: 积极缓存,谨慎失效
5. **最终一致性**: 对非关键数据接受最终一致性
6. **快速失败**: 快速返回错误而非无限重试
7. **可观察性**: 全面的日志、指标和追踪
---
## 核心组件
### 前端应用
**技术**: React 18 + TypeScript + Redux Toolkit
**结构**:
client/ ├── components/ # 可重用UI组件 ├── pages/ # 路由级别页面 ├── store/ # Redux状态管理 ├── api/ # API客户端 ├── hooks/ # 自定义React钩子 └── utils/ # 工具函数
**关键功能**:
- 服务器端渲染 (SSR) 用于SEO
- 按路由代码分割
- 渐进式Web应用 (PWA) 能力
- 乐观UI更新
- 离线支持 (服务工作者)
**状态管理**:
- **Redux**: 全局应用状态
- **React Query**: 服务器状态缓存
- **本地存储**: 用户偏好、购物车 (访客用户)
**性能目标**:
- 首次内容绘制: <1.5秒
- 可交互时间: <3秒
- Lighthouse分数: >90
---
### API网关
**技术**: Express.js + TypeScript
**责任**:
- 请求路由
- 认证/授权
- 速率限制
- 请求/响应转换
- API版本控制
- CORS处理
**中间件管道**:
```javascript
请求
↓
日志 (Morgan)
↓
速率限制 (express-rate-limit)
↓
CORS (cors)
↓
认证 (JWT验证)
↓
授权 (权限检查)
↓
请求验证 (Joi)
↓
路由处理器
↓
响应格式化
↓
错误处理
↓
响应
API版本控制策略:
- URL版本控制:
/api/v1/products,/api/v2/products - 同时维护2个版本
- 弃用警告在头部
- 旧版本6个月淘汰期
服务模块
认证服务
责任:
- 用户注册和登录
- JWT令牌生成和验证
- 密码重置流程
- OAuth集成 (Google, Facebook)
- 多因素认证 (MFA)
数据库模式:
users (
id UUID PRIMARY KEY,
email VARCHAR UNIQUE NOT NULL,
password_hash VARCHAR NOT NULL,
email_verified BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP,
updated_at TIMESTAMP
)
sessions (
id UUID PRIMARY KEY,
user_id UUID REFERENCES users(id),
token_hash VARCHAR NOT NULL,
expires_at TIMESTAMP,
created_at TIMESTAMP
)
oauth_accounts (
id UUID PRIMARY KEY,
user_id UUID REFERENCES users(id),
provider VARCHAR NOT NULL, -- 'google', 'facebook'
provider_user_id VARCHAR NOT NULL,
access_token VARCHAR,
refresh_token VARCHAR,
UNIQUE(provider, provider_user_id)
)
安全措施:
- 密码使用Argon2id哈希
- JWT令牌15分钟过期
- 刷新令牌7天过期
- 速率限制: 每15分钟5次登录尝试
- 10次失败尝试后账户锁定
- 通过TOTP的MFA (Google Authenticator)
产品服务
责任:
- 产品CRUD操作
- 库存管理
- 搜索和过滤
- 产品推荐
- 类别管理
数据库模式:
products (
id UUID PRIMARY KEY,
merchant_id UUID REFERENCES users(id),
name VARCHAR NOT NULL,
description TEXT,
price DECIMAL(10,2) NOT NULL,
inventory_count INTEGER NOT NULL DEFAULT 0,
category_id UUID REFERENCES categories(id),
status VARCHAR DEFAULT 'draft', -- draft, active, archived
created_at TIMESTAMP,
updated_at TIMESTAMP
)
product_images (
id UUID PRIMARY KEY,
product_id UUID REFERENCES products(id) ON DELETE CASCADE,
url VARCHAR NOT NULL,
position INTEGER,
created_at TIMESTAMP
)
categories (
id UUID PRIMARY KEY,
name VARCHAR NOT NULL,
parent_id UUID REFERENCES categories(id),
slug VARCHAR UNIQUE NOT NULL
)
搜索实现:
- PostgreSQL全文搜索与三元组索引
- Elasticsearch用于高级功能 (计划中)
- 缓存: 产品列表5分钟TTL, 单个产品1小时
性能优化:
- 常用查询字段数据库索引
- 通过急切加载防止N+1查询
- 带自动调整大小的图片CDN
- 使用Redis的积极缓存
订单服务
责任:
- 购物车管理
- 订单创建和处理
- 订单状态追踪
- 订单历史
- 发票生成
数据库模式:
orders (
id UUID PRIMARY KEY,
customer_id UUID REFERENCES users(id),
status VARCHAR NOT NULL, -- pending, paid, shipped, delivered, cancelled
subtotal DECIMAL(10,2) NOT NULL,
tax DECIMAL(10,2) NOT NULL,
shipping DECIMAL(10,2) NOT NULL,
total DECIMAL(10,2) NOT NULL,
payment_id VARCHAR,
shipping_address_id UUID REFERENCES addresses(id),
created_at TIMESTAMP,
updated_at TIMESTAMP
)
order_items (
id UUID PRIMARY KEY,
order_id UUID REFERENCES orders(id) ON DELETE CASCADE,
product_id UUID REFERENCES products(id),
quantity INTEGER NOT NULL,
price DECIMAL(10,2) NOT NULL,
product_snapshot JSONB -- 购买时的产品详情
)
order_events (
id UUID PRIMARY KEY,
order_id UUID REFERENCES orders(id),
event_type VARCHAR NOT NULL, -- created, paid, shipped, etc.
metadata JSONB,
created_at TIMESTAMP
)
订单状态机:
pending → paid → processing → shipped → delivered
↓ ↓ ↓ ↓
└───────┴─────────┴───────────┴──→ cancelled
交易处理:
- 订单创建的数据库事务
- 支付处理的幂等键
- 库存预留系统
- 支付失败时自动回滚
支付服务
责任:
- 支付意图创建
- 支付处理 (通过Stripe)
- 退款处理
- 支付方法管理
- 交易历史
与Stripe的集成:
// 支付意图流程
1. 客户端请求支付意图
↓
2. 服务器创建Stripe PaymentIntent
↓
3. 客户端收集支付详情
↓
4. 客户端与Stripe确认支付
↓
5. Stripe webhook通知服务器
↓
6. 服务器更新订单状态
Webhook安全:
- Stripe签名验证
- 幂等的webhook处理
- 使用作业队列的异步处理
- 失败webhook的重试逻辑
数据库模式:
payments (
id UUID PRIMARY KEY,
order_id UUID REFERENCES orders(id),
stripe_payment_intent_id VARCHAR UNIQUE,
amount DECIMAL(10,2) NOT NULL,
status VARCHAR NOT NULL, -- pending, succeeded, failed
payment_method VARCHAR, -- card, bank_transfer
metadata JSONB,
created_at TIMESTAMP,
updated_at TIMESTAMP
)
refunds (
id UUID PRIMARY KEY,
payment_id UUID REFERENCES payments(id),
stripe_refund_id VARCHAR UNIQUE,
amount DECIMAL(10,2) NOT NULL,
reason VARCHAR,
status VARCHAR NOT NULL,
created_at TIMESTAMP
)
数据架构
数据库设计
主数据库: PostgreSQL 14
模式组织:
- 公共模式: 核心应用表
- 审计模式: 审计日志和事件溯源
- 分析模式: 用于报告的降维数据
连接池:
{
max: 20, // 最大连接
min: 5, // 最小连接
idle: 10000, // 空闲连接10秒后关闭
acquire: 30000, // 获取连接的最大时间
evict: 1000 // 每1秒检查空闲连接
}
备份策略:
- 自动化每日备份 (RDS快照)
- 启用时间点恢复 (7天窗口)
- 月度备份保留1年
- 季度测试备份
缓存策略
Redis配置:
- 部署: AWS ElastiCache (Redis 7.0)
- 模式: 启用集群模式
- 节点: 3 (主 + 2 副本)
- 驱逐策略: LRU (最近最少使用)
缓存模式:
- 缓存旁路 (读重数据):
async function getProduct(id) {
// 先尝试缓存
let product = await cache.get(`product:${id}`);
if (!product) {
// 缓存未命中 - 从数据库获取
product = await db.products.findById(id);
// 存储到缓存 (1小时TTL)
await cache.set(`product:${id}`, product, 3600);
}
return product;
}
- 直写 (关键数据):
async function updateProduct(id, data) {
// 更新数据库
const product = await db.products.update(id, data);
// 更新缓存
await cache.set(`product:${id}`, product, 3600);
return product;
}
缓存失效:
// 产品更新
await cache.del(`product:${productId}`);
await cache.del(`products:merchant:${merchantId}`);
await cache.del(`products:category:${categoryId}`);
// 模式基础失效
await cache.delPattern(`products:*`);
缓存内容:
| 数据类型 | TTL | 理由 |
|---|---|---|
| 产品详情 | 1 小时 | 不常更新 |
| 产品列表 | 5 分钟 | 频繁更新 |
| 用户会话 | 15 分钟 | 安全要求 |
| 搜索结果 | 10 分钟 | 昂贵查询 |
| API响应 | 1 分钟 | 速率限制保护 |
数据迁移策略
工具: Prisma Migrate (开发), 自定义脚本 (生产)
迁移过程:
- 在开发中创建迁移
- 在PR中审查SQL
- 在暂存测试 (生产数据副本)
- 在低流量窗口运行到生产
- 文档化回滚计划
零停机迁移:
-- 示例: 添加非空列
-- 步骤 1: 添加列作为可空
ALTER TABLE products ADD COLUMN new_field VARCHAR;
-- 步骤 2: 回填数据
UPDATE products SET new_field = 'default_value' WHERE new_field IS NULL;
-- 步骤 3: 添加 NOT NULL 约束
ALTER TABLE products ALTER COLUMN new_field SET NOT NULL;
基础设施
AWS架构
区域: 主: us-east-1, 灾难恢复: us-west-2
VPC设计:
VPC (10.0.0.0/16)
├── 公共子网 (10.0.1.0/24, 10.0.2.0/24)
│ ├── NAT网关
│ └── 应用负载均衡器
└── 私有子网 (10.0.10.0/24, 10.0.11.0/24)
├── ECS任务 (应用)
├── RDS (数据库)
└── ElastiCache (Redis)
计算:
- ECS Fargate: 应用的无服务器容器
- 自动扩展: 目标CPU 70%, 最小2任务, 最大10任务
- 任务定义:
CPU: 1024 (1 vCPU) Memory: 2048 MB Container Port: 3000 Environment: Production
数据库:
- RDS PostgreSQL: db.r5.large (2 vCPU, 16 GB RAM)
- 多可用区: 是 (自动故障转移)
- 读取副本: 1 (用于分析查询)
- 存储: 500 GB GP3 (启用自动扩展)
存储:
- S3桶: product-images-prod
- 生命周期策略: 90天后移动到Glacier
- CDN: 图片的CloudFront分发
- 备份: 启用跨区域复制
网络:
- 负载均衡器: 应用负载均衡器 (ALB)
- SSL/TLS: ACM证书 (自动续订)
- WAF: 带OWASP规则的AWS WAF
- DDoS防护: AWS Shield Standard
部署架构
CI/CD管道 (GitHub Actions):
代码推送
↓
自动化测试 (单元 + 集成)
↓
代码检查和类型检查
↓
构建Docker镜像
↓
推送到ECR (Elastic Container Registry)
↓
部署到暂存 (自动)
↓
集成测试 (暂存)
↓
手动批准
↓
部署到生产 (金丝雀)
↓
监控指标 (15分钟)
↓
完全推出或回滚
部署策略: 蓝绿与金丝雀
生产 (蓝) 金丝雀 (绿)
100%流量 → 95% / 5% 分割 → 0% / 100%
↓
监控15分钟
↓
成功? 完全推出 : 回滚
回滚程序:
- 检测问题 (自动化警报或手动)
- 触发回滚命令
- 将流量路由回先前版本
- 调查根因
- 修复并重新部署
部署窗口:
- 暂存: 随时
- 生产: 周二-周四, 10 AM - 2 PM EST
- 紧急: 24/7 随叫随到批准
安全架构
深度防御
层 1: 网络安全
- VPC隔离
- 安全组 (仅允许列表)
- 网络ACL
- 数据层的私有子网
- 出站流量的NAT网关
层 2: 应用安全
- 输入验证 (所有用户输入)
- SQL注入预防 (参数化查询)
- XSS预防 (清理 + CSP头部)
- CSRF防护 (令牌)
- 速率限制 (DDoS缓解)
层 3: 认证与授权
- 短期过期的JWT
- 刷新令牌轮换
- 管理员账户的MFA
- 基于角色的访问控制 (RBAC)
- 最小权限原则
层 4: 数据安全
- 静态加密 (RDS, S3)
- 传输中加密 (TLS 1.3)
- AWS Secrets Manager中的密钥
- PII数据字段级加密
- 定期安全审计
安全头部
{
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline'",
'X-Frame-Options': 'DENY',
'X-Content-Type-Options': 'nosniff',
'Referrer-Policy': 'strict-origin-when-cross-origin',
'Permissions-Policy': 'geolocation=(), microphone=(), camera=()'
}
合规
标准:
- PCI DSS: 级别 2 (Stripe处理级别 1)
- GDPR: 用户数据权利、删除、导出
- SOC 2 Type II: 进行中 (2024 Q2)
数据保留:
- 用户数据: 保留直到账户删除
- 订单数据: 7年 (法规要求)
- 日志: 90天
- 备份: 1年
可扩展性与性能
当前容量
| 指标 | 当前 | 限制 | 余地 |
|---|---|---|---|
| 并发用户 | 500 | 2,000 | 4x |
| 请求/秒 | 200 | 1,000 | 5x |
| 数据库连接 | 50 | 200 | 4x |
| 存储 | 500 GB | 2 TB | 4x |
扩展策略
水平扩展:
- 无状态服务 (易于复制)
- 基于CPU/内存的自动扩展
- 数据库读取副本用于读重工作负载
垂直扩展:
- 数据库实例大小 (计划内停机)
- 缓存集群大小
缓存:
- 应用级缓存 (Redis)
- 静态资产的CDN
- 数据库查询结果缓存
数据库优化:
- 常用查询字段索引
- 复杂查询的物化视图
- 连接池
- 查询优化 (EXPLAIN ANALYZE)
性能预算
API响应时间 (p95):
- GET请求: <200毫秒
- POST请求: <500毫秒
- 复杂查询: <1秒
前端性能 (Lighthouse):
- 性能: >90
- 可访问性: 100
- 最佳实践: >90
- SEO: 100
数据库查询时间 (p95):
- 简单查询: <50毫秒
- 连接查询: <100毫秒
- 聚合: <500毫秒
监控与可观察性
指标
应用指标 (DataDog):
- 请求率、错误率、持续时间 (RED指标)
- 活跃用户、会话
- 业务指标 (订单、收入)
- 自定义指标 (购物车放弃率、转化率)
基础设施指标:
- CPU、内存、磁盘使用
- 网络吞吐量
- 数据库连接、查询性能
- 缓存命中率
仪表板:
- 系统健康: 整体系统状态
- API性能: 端点特定指标
- 业务指标: KPIs和转化
- 数据库性能: 查询分析
- 错误追踪: 错误率和趋势
日志
日志级别:
- ERROR: 需要调查的应用错误
- WARN: 潜在问题或性能降级
- INFO: 重大事件 (订单创建、支付成功)
- DEBUG: 详细诊断信息 (生产禁用)
日志聚合: CloudWatch Logs → DataDog
结构化日志:
logger.info('订单创建', {
orderId: '123',
customerId: '456',
total: 99.99,
timestamp: new Date().toISOString()
});
警报
警报通道:
- 关键: PagerDuty (SMS + 电话)
- 高: Slack #incidents
- 中: Slack #engineering
- 低: 邮件
警报规则:
- name: 高错误率
condition: error_rate > 5% for 5 minutes
severity: CRITICAL
channel: PagerDuty
- name: 慢API响应
condition: p95_latency > 1000ms for 10 minutes
severity: HIGH
channel: Slack
- name: 数据库连接池耗尽
condition: db_connections > 180 for 5 minutes
severity: CRITICAL
channel: PagerDuty
- name: 低缓存命中率
condition: cache_hit_rate < 70% for 15 minutes
severity: MEDIUM
channel: Slack
追踪
分布式追踪: DataDog APM
追踪示例:
HTTP请求: GET /api/products/123
├─ 认证中间件 (5ms)
├─ 授权中间件 (2ms)
├─ 产品服务
│ ├─ 缓存查找 (1ms) [未命中]
│ ├─ 数据库查询 (45ms)
│ └─ 缓存设置 (2ms)
├─ 响应序列化 (3ms)
└─ 总计: 58ms
未来考虑
计划改进 (未来6个月)
-
微服务迁移
- 先提取支付服务
- 带消息队列的事件驱动架构
- 用于服务间通信的服务网格 (Istio)
-
搜索增强
- 迁移到Elasticsearch
- 实现分面搜索
- 添加产品推荐 (基于ML)
-
性能优化
- 实现GraphQL (减少过度获取)
- 更好的SEO的服务器端渲染
- 优化数据库查询 (20%改进目标)
-
基础设施
- 多区域部署以降低延迟
- 从ECS迁移到Kubernetes
- 后台作业的无服务器函数
技术债务
高优先级:
- 升级Node.js从v16到v20
- 从类组件迁移到钩子 (React)
- 实现全面集成测试
- 重构遗留认证代码
中优先级:
- 跨服务标准化错误处理
- 改进API文档 (OpenAPI规范)
- 为关键流添加端到端测试
低优先级:
- 从REST迁移到GraphQL
- 实现BFF (后端为前端) 模式
- 添加功能标志系统
风险与缓解
| 风险 | 影响 | 概率 | 缓解 |
|---|---|---|---|
| 数据库成为瓶颈 | 高 | 中 | 读取副本、缓存、分片计划 |
| 单体难以扩展 | 中 | 高 | 模块化架构、迁移计划 |
| 第三方服务中断 | 高 | 低 | 备援策略、断路器 |
| 安全漏洞 | 关键 | 低 | 定期审计、渗透测试 |
| 关键工程师离职 | 中 | 中 | 文档化、知识共享 |
附录
术语表
- GMV: 总商品价值
- RPS: 每秒请求数
- p95: 第95百分位
- TTL: 生存时间
- CDN: 内容分发网络
- WAF: Web应用防火墙
参考
变更日志
| 版本 | 日期 | 变更 | 作者 |
|---|---|---|---|
| 2.3 | 2024-01-15 | 添加金丝雀部署策略 | Alice |
| 2.2 | 2023-12-01 | 更新基础设施 (ECS迁移) | Bob |
| 2.1 | 2023-10-15 | 添加安全架构部分 | Frank |
| 2.0 | 2023-09-01 | 主要修订 - 微服务计划 | Alice, Bob |
文档状态: 当前 下次审查: 2024年4月15日 维护者: 工程团队 问题: Slack上的 #architecture
### 架构决策记录 (ADR) 模板
```markdown
# ADR-015: 从会话迁移到JWT认证
**状态**: 已接受
**日期**: 2024年1月15日
**决策者**: Alice (EM), Bob (技术主管), Carol (前端主管)
**咨询**: 安全团队、DevOps团队
---
## 上下文
我们当前的认证系统使用存储在Redis中的服务器端会话。随着我们扩展到支持更多用户并准备多区域部署,会话管理已成为瓶颈。
### 当前状态
**基于会话的认证**:
```javascript
// 登录创建服务器端会话
app.post('/login', (req, res) => {
const user = authenticate(req.body);
req.session.userId = user.id; // 存储在Redis中
res.json({ success: true });
});
// 每个请求验证会话
app.use((req, res, next) => {
if (req.session.userId) {
req.user = await getUser(req.session.userId);
}
next();
});
问题:
- 可扩展性: 每个请求需要Redis查找 (增加5-10毫秒延迟)
- 复杂性: 跨区域会话复制复杂
- 内存: 50,000活跃会话 = 250MB Redis内存
- 有状态: 无法轻松添加新服务器 (需要粘性会话)
要求
- 无状态: 无服务器端会话存储
- 可扩展: 支持50k+并发用户
- 安全: 抵抗常见攻击 (XSS, CSRF, 令牌盗窃)
- 快速: 最小性能影响 (<1毫秒开销)
- 兼容: 与现有移动应用工作
决策
我们将从基于会话的认证迁移到JSON Web Tokens (JWT)。
实现
基于JWT的认证:
// 登录生成JWT
app.post('/login', (req, res) => {
const user = authenticate(req.body);
const accessToken = jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
const refreshToken = jwt.sign(
{ userId: user.id },
process.env.REFRESH_SECRET,
{ expiresIn: '7d' }
);
res.json({ accessToken, refreshToken });
});
// 每个请求验证JWT (无数据库查找)
app.use((req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
try {
req.user = jwt.verify(token, process.env.JWT_SECRET);
next();
} catch (error) {
res.status(401).json({ error: '无效令牌' });
}
});
令牌结构
访问令牌 (短期):
- 载荷:
{ userId, role, permissions } - 过期: 15分钟
- 签名: HMAC SHA256
刷新令牌 (长期):
- 载荷:
{ userId } - 过期: 7天
- 存储在数据库中的哈希 (用于撤销)
考虑的替代方案
替代方案 1: 保持基于会话的认证
优点:
- 无需迁移
- 团队熟悉
- 易于撤销访问 (删除会话)
缺点:
- 可扩展性问题持续
- 复杂多区域设置
- 需要粘性会话 (负载均衡器复杂性)
决策: 由于可扩展性问题被拒绝
替代方案 2: 仅OAuth 2.0
优点:
- 行业标准
- 委托能力
- 经过良好测试的安全
缺点:
- 对我们的用例过度设计
- 复杂实现
- 需要授权服务器
- 用户期望用户名/密码
决策: 被拒绝 - 当前需求过于复杂。稍后将添加OAuth作为选项。
替代方案 3: API密钥
优点:
- 简单实现
- 无状态
- 易于撤销
缺点:
- 无过期 (安全风险)
- 不适合用户认证
- 无声明/范围
决策: 被拒绝 - 更适合程序化访问,而非用户认证
后果
正面
-
性能: 消除每个请求的Redis查找
- 预计改进: 5-10毫秒每个请求
- 减少Redis负载80%
-
可扩展性: 无状态服务器
- 无需粘性会话
- 易于水平扩展
- 多区域部署简化
-
移动支持: 更好的移动应用体验
- 令牌本地存储
- 无需cookie
- 离线令牌验证
-
开发者体验: 更简单架构
- 无会话中间件
- 更易于测试 (无会话状态)
- 清晰的令牌生命周期
负面
-
令牌撤销: 无法立即撤销访问
- 缓解: 短期令牌过期 (15分钟)
- 缓解: 刷新令牌黑名单
- 缓解: 紧急: 强制所有用户重新认证
-
令牌大小: JWTs大于会话ID
- 会话ID: ~32字节
- JWT: ~200字节
- 影响: 最小 (每个请求200字节可接受)
-
密钥管理: JWT密钥是关键
- 缓解: 存储在AWS Secrets Manager
- 缓解: 季度轮换密钥
- 缓解: 不同环境的密钥
-
XSS风险: 令牌可被JavaScript访问
- 缓解: 存储在httpOnly cookie中 (可能时)
- 缓解: 严格内容安全策略
- 缓解: 短期令牌过期
风险
| 风险 | 严重性 | 缓解 |
|---|---|---|
| JWT密钥泄漏 | 关键 | Secrets Manager、轮换、监控 |
| 无法撤销受损令牌 | 高 | 短期过期、刷新令牌黑名单 |
| 算法混淆攻击 | 中 | 在验证中明确指定算法 |
| 重放攻击 | 中 | 短期过期、仅HTTPS |
实现计划
阶段 1: 准备 (第1-2周)
- [ ] 创建JWT工具函数
- [ ] 更新认证中间件
- [ ] 添加刷新令牌端点
- [ ] 为前端团队编写迁移指南
- [ ] 在AWS Secrets Manager中设置密钥
阶段 2: 后端迁移 (第3-4周)
- [ ] 部署JWT端点与会话端点并行
- [ ] 为JWT认证添加功能标志
- [ ] 全面测试 (单元 + 集成)
- [ ] 用JWTs进行负载测试
- [ ] 安全审查
阶段 3: 前端迁移 (第5-6周)
- [ ] 更新Web应用使用JWT
- [ ] 更新移动应用使用JWT
- [ ] 渐进推出 (10% → 50% → 100%)
- [ ] 监控错误率和性能
阶段 4: 清理 (第7-8周)
- [ ] 移除基于会话的认证代码
- [ ] 移除Redis会话存储
- [ ] 更新文档
- [ ] 事后分析和经验教训
回滚计划
如果出现关键问题:
- 禁用JWT功能标志
- 将所有流量路由到会话端点
- 保留JWT代码进行调查
- 识别并修复问题
- 恢复迁移
成功指标
性能:
- [ ] 平均请求延迟减少5毫秒
- [ ] p95延迟减少10毫秒
- [ ] Redis CPU使用减少80%
可靠性:
- [ ] 认证错误无增加
- [ ] <0.1% 令牌验证失败
- [ ] 零安全事件
用户体验:
- [ ] 登录流程不变 (透明迁移)
- [ ] 支持工单无增加
- [ ] 移动应用性能改进
安全考虑
令牌安全:
- 令牌使用HS256签名 (HMAC SHA256)
- 密钥: 256位随机生成
- 密钥季度轮换
- 验证中指定算法 (防止算法混淆)
存储:
- Web: httpOnly cookies (防止XSS)
- 移动: 安全存储 (Keychain/Keystore)
- 绝不存储在localStorage (XSS易受攻击)
传输:
- 仅HTTPS (TLS 1.3)
- 安全、SameSite=Strict cookies
- 无令牌在URL中 (日志暴露)
验证:
- 验证签名
- 检查过期
- 验证发行者和受众
- 检查令牌未在黑名单中 (刷新令牌)
参考
更新
| 日期 | 更新 | 作者 |
|---|---|---|
| 2024-01-15 | 初始ADR创建 | Bob |
| 2024-01-20 | 添加安全审查反馈 | Frank |
| 2024-02-01 | 实现后更新 | Bob |
状态: 已接受 取代: ADR-008 (基于会话的认证) 相关: ADR-012 (API安全), ADR-014 (多区域部署)
## 使用示例
@architecture-documenter @architecture-documenter --type system-overview @architecture-documenter --type adr @architecture-documenter --focus security @architecture-documenter --focus scalability @architecture-documenter --include-diagrams @architecture-documenter --update-existing
## 最佳实践
### 文档化架构决策
**何时创建ADR**:
- 重大技术决策
- 架构变更
- 技术选择
- 过程变更
- 安全决策
**ADR结构**:
1. **上下文**: 情况是什么?
2. **决策**: 我们决定了什么?
3. **替代方案**: 我们还考虑了哪些?
4. **后果**: 影响是什么?
### 使用视觉图表
**图表类型**:
- **系统上下文**: 显示系统边界
- **容器**: 显示高层架构
- **组件**: 显示内部结构
- **代码**: 显示类/模块关系
- **部署**: 显示基础设施
- **序列**: 显示随时间交互
**工具**:
- 图表即代码: Mermaid, PlantUML
- 视觉工具: Lucidchart, Draw.io
- 云特定: AWS架构图表
### 保持文档最新
**文档生命周期**:
- 在设计阶段创建
- 在代码审查中审查
- 随实现变更更新
- 季度架构审查
- 归档过时文档 (不删除)
**版本控制**:
- 将文档与代码存储
- 随版本版本化
- 链接文档到特定代码版本
- 维护变更日志
### 使其可发现
**组织**:
- 中央位置 (wiki, docs文件夹)
- 清晰的命名约定
- 目录
- 交叉引用
- 搜索友好
**可访问性**:
- 组织内公开
- 易于导航
- 多个入口点
- 从README链接
## 笔记
- 架构文档用于沟通,而非完美
- 图表胜于言语 - 自由使用
- ADRs捕捉决策和上下文供未来参考
- 保持文档与代码变更同步
- 版本化架构文档随代码
- 定期审查防止文档漂移
- 好的架构文档显著减少入职时间
- 文档“为什么”而不仅是“什么”
- 包括权衡和考虑的替代方案
- 明确安全和可扩展性
- 链接架构到业务目标
- 使用一致的符号和术语