Skip to Content
Handbook第8章: 持续成长与进阶架构思维与系统设计

8.2 架构思维与系统设计

从功能到架构

新手的误区

❌ 错误思路: "用户需要注册 → 创建用户表 → 实现注册功能" "用户需要登录 → 创建session → 实现登录功能" 问题:只看到表面需求,没有考虑整体架构
✅ 正确思路: "用户系统是核心基础设施,需要考虑: - 认证 vs 授权 - 单点登录 (SSO) - 安全策略 - 扩展性 - 性能要求 - 数据一致性"

架构思维的核心

4个维度

1. 功能维度 ├─ 核心功能:必须有的 ├─ 辅助功能:提升体验的 └─ 扩展功能:未来可能加的 2. 数据维度 ├─ 数据模型:实体关系 ├─ 数据流向:业务流程 └─ 数据存储:选择数据库 3. 技术维度 ├─ 前端架构:单页/多页/SSR/SSG ├─ 后端架构:单体/微服务/无服务器 └─ 部署架构:云/容器/边缘 4. 业务维度 ├─ 用户画像:谁在使用 ├─ 使用场景:何时何地使用 └─ 商业目标:如何盈利

架构决策框架 (ADR)

ADR 模板

架构决策记录 (Architecture Decision Record)

# ADR-001: 选择 Next.js 作为前端框架 ## 背景 我们需要为 SaaS 产品选择前端框架,团队有 React 经验,产品需要 SEO 友好。 ## 决策 选择 Next.js 14 (App Router) ## 理由 ✅ SSR/SSG 支持,SEO友好 ✅ 团队已有 React 经验 ✅ 丰富的生态系统 ✅ Vercel 原生支持,部署简单 ✅ 混合渲染模式灵活 ## 备选方案 - Remix:更注重 Web 标准,但生态较小 - Nuxt.js:Vue 生态,团队不熟悉 - Astro:静态站点强,但交互性一般 ## 后果 ✅ 收益:开发效率高,SEO好,部署简单 ⚠️ 注意:需要学习 Next.js 特有概念

决策记录模板

编号:ADR-[序号] 标题:[简洁描述] 状态:[已提议/已接受/已废弃/已替代] ## 背景 [问题的上下文] ## 决策 [我们决定做什么] ## 理由 [为什么做这个决定] ## 备选方案 [考虑过的其他方案] ## 后果 [正面影响/负面影响/未知]

系统分层架构

三层架构模型

表示层 (Presentation Layer) ├─ 前端应用 (React/Vue) ├─ 移动端 (React Native/Flutter) ├─ 管理后台 (Admin Panel) └─ API 文档 (Swagger/OpenAPI) 业务逻辑层 (Business Logic Layer) ├─ 用户服务 (User Service) ├─ 订单服务 (Order Service) ├─ 支付服务 (Payment Service) └─ 通知服务 (Notification Service) 数据访问层 (Data Access Layer) ├─ ORM/ODM (Prisma/TypeORM) ├─ 数据库 (PostgreSQL/MySQL) ├─ 缓存 (Redis/Memcached) └─ 文件存储 (S3/Cloudinary)

分层设计原则

依赖倒置

// ❌ 错误:上层依赖下层 class UserService { private db = new PostgreSQLDatabase() private redis = new RedisCache() } // ✅ 正确:依赖抽象 interface DatabaseInterface { query(sql: string): Promise<any> } interface CacheInterface { get(key: string): Promise<string> set(key: string, value: string): Promise<void> } class UserService { constructor( private db: DatabaseInterface, private cache: CacheInterface ) {} }

微服务 vs 单体

选择指南

小型产品 (1-3人团队)

推荐:单体架构 技术栈:Next.js + PostgreSQL + Prisma 优点: ✅ 开发简单 ✅ 部署容易 ✅ 调试方便 ✅ 团队学习成本低 适用场景: - MVP阶段 - 简单业务逻辑 - 有限用户量 (< 10万)

中型产品 (5-15人团队)

推荐:模块化单体 技术栈:Next.js + NestJS + PostgreSQL 优点: ✅ 保持单体简单性 ✅ 内部模块化 ✅ 未来可平滑迁移 架构: src/ ├─ modules/ │ ├─ users/ │ ├─ orders/ │ └─ payments/ ├─ shared/ │ ├─ database/ │ ├─ auth/ │ └─ utils/

大型产品 (15人+团队)

推荐:微服务架构 技术栈:Node.js/Python/Go + Kubernetes 优点: ✅ 独立部署 ✅ 技术栈灵活 ✅ 团队自治 ✅ 故障隔离 挑战: ⚠️ 运维复杂 ⚠️ 数据一致性 ⚠️ 调试困难

数据架构设计

数据库设计流程

第1步:实体建模

第2步:关系分析

1:1 关系 - 用户 ↔ 用户资料 1:N 关系 - 项目 → 任务 - 用户 → 订单 N:M 关系 - 用户 ↔ 项目 (通过成员表) - 项目 ↔ 标签 (通过关联表)

第3步:性能优化

-- 索引设计 CREATE INDEX idx_tasks_project_id ON tasks(project_id); CREATE INDEX idx_tasks_assignee_id ON tasks(assignee_id); CREATE INDEX idx_tasks_status ON tasks(status); -- 复合索引 CREATE INDEX idx_tasks_project_status ON tasks(project_id, status); -- 部分索引 CREATE INDEX idx_active_projects ON projects(id) WHERE status = 'active';

缓存策略

多级缓存

L1: 浏览器缓存 ├─ 静态资源 (CSS/JS/图片) │ └─ 缓存时间:1年 └─ HTML页面 └─ 缓存时间:5分钟 L2: CDN缓存 ├─ 静态资源 │ └─ 缓存时间:1年 └─ API响应 (GET请求) └─ 缓存时间:1小时 L3: 服务器缓存 ├─ Redis │ ├─ 用户会话:24小时 │ ├─ API响应:1小时 │ └─ 数据库查询:30分钟 └─ 应用内存 ├─ 配置信息:永不过期 └─ 热门数据:10分钟 L4: 数据库缓存 ├─ 查询缓存 └─ 缓冲池

缓存失效策略

// 写透策略 (Write-Through) async updateUser(id: string, data: UserData) { // 1. 更新数据库 await db.users.update(id, data) // 2. 更新缓存 await cache.set(`user:${id}`, data) } // 写回策略 (Write-Back) async updateUser(id: string, data: UserData) { // 1. 只更新缓存 await cache.set(`user:${id}`, data) // 2. 异步写入数据库 queue.add(async () => { await db.users.update(id, data) }) } // 失效策略 (Write-Around) async updateUser(id: string, data: UserData) { // 1. 更新数据库 await db.users.update(id, data) // 2. 删除缓存 await cache.delete(`user:${id}`) }

API设计最佳实践

RESTful设计

资源命名

✅ 正确: GET /api/users // 获取用户列表 GET /api/users/:id // 获取特定用户 POST /api/users // 创建用户 PUT /api/users/:id // 更新用户 DELETE /api/users/:id // 删除用户 ❌ 错误: GET /api/getUsers POST /api/createUser GET /api/user/:id/delete

状态码使用

2xx - 成功 200 OK - 请求成功 201 Created - 资源创建成功 204 No Content - 删除成功 4xx - 客户端错误 400 Bad Request - 请求参数错误 401 Unauthorized - 未认证 403 Forbidden - 无权限 404 Not Found - 资源不存在 409 Conflict - 资源冲突 5xx - 服务器错误 500 Internal Server Error - 服务器错误 503 Service Unavailable - 服务不可用

GraphQL vs REST

REST 适用场景

✅ 简单CRUD操作 ✅ 静态数据展示 ✅ 缓存友好 ✅ HTTP语义清晰 示例: GET /api/products GET /api/products/:id POST /api/products

GraphQL 适用场景

✅ 复杂数据查询 ✅ 客户端灵活获取数据 ✅ 减少网络请求 ✅ 强类型系统 示例: query { product(id: "123") { name price reviews { author content rating } } }

事件驱动架构

事件模式

简单事件

// 事件定义 interface UserRegisteredEvent { type: 'user.registered' payload: { userId: string email: string timestamp: Date } } // 事件发布 class UserService { async register(data: RegisterData) { const user = await db.users.create(data) // 发布事件 eventBus.publish({ type: 'user.registered', payload: { userId: user.id, email: user.email, timestamp: new Date() } }) return user } } // 事件订阅 eventBus.subscribe('user.registered', async (event) => { // 发送欢迎邮件 await emailService.sendWelcomeEmail(event.payload.email) // 创建默认设置 await settingsService.createDefault(event.payload.userId) // 记录分析事件 await analytics.track('user_registered', event.payload) })

CQRS模式

命令查询职责分离

// 命令 (写操作) class CreateOrderCommand { constructor( public readonly userId: string, public readonly items: OrderItem[], public readonly total: number ) {} } class CreateOrderHandler { async handle(command: CreateOrderCommand) { // 1. 验证 await this.validator.validate(command) // 2. 创建订单 const order = await db.orders.create({ userId: command.userId, items: command.items, total: command.total, status: 'pending' }) // 3. 发布事件 eventBus.publish(new OrderCreatedEvent(order)) return order } } // 查询 (读操作) class GetOrderQuery { constructor( public readonly orderId: string ) {} } class GetOrderHandler { async handle(query: GetOrderQuery) { // 从读模型 (优化后的视图) 获取 return await readDb.orders.findOne(query.orderId) } }

安全架构

安全层级

第1层:网络安全 ├─ HTTPS (SSL/TLS) ├─ CORS 配置 ├─ DDoS 防护 └─ WAF (Web应用防火墙) 第2层:应用安全 ├─ 身份认证 (OAuth/JWT) ├─ 授权控制 (RBAC) ├─ 输入验证 ├─ 输出编码 └─ CSRF 防护 第3层:数据安全 ├─ 敏感数据加密 ├─ 密码哈希 (bcrypt) ├─ 数据库加密 ├─ 备份加密 └─ 审计日志 第4层:运维安全 ├─ 访问控制 ├─ 密钥管理 ├─ 漏洞扫描 ├─ 安全审计 └─ 应急响应

安全检查清单

## 认证安全 - [ ] 所有API都需要认证 (除了公开接口) - [ ] 密码使用强哈希算法 (bcrypt/argon2) - [ ] JWT使用强密钥和合理过期时间 - [ ] 多因素认证 (2FA) 支持 ## 授权安全 - [ ] 最小权限原则 - [ ] 基于角色的访问控制 (RBAC) - [ ] 资源级权限检查 - [ ] 避免水平越权 ## 输入验证 - [ ] 服务端验证所有输入 - [ ] 使用白名单验证 - [ ] 限制输入长度 - [ ] SQL注入防护 (参数化查询) ## 数据保护 - [ ] 敏感数据加密存储 - [ ] API响应过滤敏感字段 - [ ] 日志不记录敏感信息 - [ ] 定期备份和恢复测试

架构演进策略

渐进式架构

阶段1:MVP (Month 1-2)

简单单体 Next.js + PostgreSQL - 核心功能 - 用户认证 - 基础管理

阶段2:增长 (Month 3-6)

模块化单体 - 模块拆分 - 缓存引入 - 数据库优化 - CDN部署

阶段3:扩展 (Month 6-12)

服务化 - 独立服务 - 事件驱动 - 异步处理 - 监控完善

重构时机

需要重构的信号

🔴 红色警告 - 代码耦合严重,难以修改 - 性能问题持续恶化 - 部署时间超过30分钟 - 团队开发速度明显下降 - 线上bug频繁出现 🟡 黄色注意 - 新功能开发时间变长 - 技术债务积累过多 - 测试覆盖率低于60% - 文档严重滞后 🟢 绿色正常 - 新功能1-2天交付 - 测试覆盖率>80% - 性能稳定 - 部署自动化

架构决策原则

原则1:简单性优先

优先选择简单的解决方案 直到复杂度不可避免 简单 = 容易理解 + 容易维护 + 容易扩展

原则2:可观测性

设计时考虑监控和调试 - 日志记录 - 性能指标 - 错误追踪 - 链路追踪

原则3:渐进式演进

不要过度设计 从简单开始 根据需求演进 "优雅的退化" > "过早的优化"

原则4:人本主义

技术服务于人 考虑团队能力和认知负担 最好的架构是团队能理解和维护的架构

记住:架构设计不是一次性决策,而是一个持续演进的过程。保持灵活性,拥抱变化。

Last updated on