2-2-1-架构不是设计出来的是长出来的
2.2.1 架构不是设计出来的,是长出来的
引言
项目开始时,你可能会想:
"我要设计一个完美的架构,能应对未来所有需求!"
- 微服务?准备好了
- 消息队列?部署好了
- 缓存层?配置好了
- 分布式数据库?搭建好了
三个月后,你发现:
- 只有 100 个用户,微服务是过度设计
- 消息队列从未用过,增加了运维负担
- 缓存层没有命中率,因为数据量太小
- 分布式数据库的复杂度超过了收益
架构不是在第一天就设计完美的,而是在真实压力下逐步演化出来的。
设计 vs 演化
设计思维:Big Design Up Front
# 第一天就设计完整的架构
# 1. 分层架构
project/
├── domain/ # 领域层
├── application/ # 应用层
├── infrastructure/ # 基础设施层
├── presentation/ # 表现层
# 2. 抽象接口
class Repository(ABC):
@abstractmethod
def find(self, id): ...
class Service(ABC):
@abstractmethod
def execute(self, request): ...
# 3. 依赖注入容器
container = DependencyContainer()
container.register(UserRepository, MySQLUserRepository)
container.register(UserService, DefaultUserService)
# 问题:
# - 你只有1个功能,但架构支持100个功能
# - 你不知道真正的瓶颈在哪里
# - 过度抽象让简单的事情变复杂
问题:
- 浪费时间在可能永远不需要的抽象上
- 过早的优化是万恶之源
- 架构假设可能与现实不符
演化思维:从简单开始
# 第一天:最简单的实现
# app.py
from flask import Flask, request, jsonify
app = Flask(__name__)
users = [] # 先用内存存储
@app.route('/users', methods=['POST'])
def create_user():
user = request.get_json()
users.append(user)
return jsonify(user), 201
# 够用就行,先验证想法
第 1 周:用户增长,需要持久化
# 添加数据库
import sqlite3
def create_user():
user = request.get_json()
db = sqlite3.connect('users.db')
db.execute('INSERT INTO users (name) VALUES (?)', (user['name'],))
db.commit()
return jsonify(user), 201
# 还是很简单,但已经持久化了
第 1 个月:逻辑变复杂,提取服务层
# user_service.py
class UserService:
def __init__(self, db_path):
self.db_path = db_path
def create_user(self, name):
db = sqlite3.connect(self.db_path)
db.execute('INSERT INTO users (name) VALUES (?)', (name,))
db.commit()
# app.py
user_service = UserService('users.db')
@app.route('/users', methods=['POST'])
def create_user():
data = request.get_json()
user_service.create_user(data['name'])
return jsonify({'status': 'ok'}), 201
# 分层出现了,但是基于真实需求
第 3 个月:性能问题,添加缓存
# 现在真的需要缓存了
from functools import lru_cache
class UserService:
@lru_cache(maxsize=100)
def get_user(self, user_id):
# 缓存热点数据
db = sqlite3.connect(self.db_path)
result = db.execute('SELECT * FROM users WHERE id = ?', (user_id,))
return result.fetchone()
# 缓存是因为性能瓶颈,不是因为"应该有"
第 6 个月:并发量上升,迁移到 PostgreSQL + Redis
# 真实压力驱动架构演化
class UserService:
def __init__(self, db, cache):
self.db = db # PostgreSQL
self.cache = cache # Redis
def get_user(self, user_id):
# 先查缓存
cached = self.cache.get(f'user:{user_id}')
if cached:
return cached
# 缓存未命中,查数据库
user = self.db.query(User).get(user_id)
self.cache.set(f'user:{user_id}', user)
return user
# 架构是"长"出来的,不是第一天设计的
架构演化的驱动力
驱动力1:真实的性能瓶颈
# 不要提前优化
# ❌ 错误
"我们可能会有很多用户,所以先做分布式架构"
# ✅ 正确
"我们现在有10万用户,单机数据库响应时间超过500ms,需要分库分表"
真实案例:Instagram
- 创始之初:单机 PostgreSQL
- 用户量小时:足够快
- 百万用户后:才开始分片
- 架构随真实需求演化
驱动力2:业务复杂度增加
# 一开始
def create_order(user_id, items):
order = Order(user_id=user_id, items=items)
db.save(order)
return order
# 业务复杂后
def create_order(user_id, items):
# 1. 验证库存
inventory.check_stock(items)
# 2. 计算价格(优惠、税费)
price_calculator.calculate(items, user_id)
# 3. 扣减库存
inventory.reserve(items)
# 4. 创建订单
order = Order(user_id=user_id, items=items)
order_repository.save(order)
# 5. 发送通知
notification_service.send_order_created(order)
# 逻辑复杂了,自然需要分层和模块化
驱动力3:团队规模扩大
# 1人团队:一个文件就够
# app.py - 500行代码
# 3人团队:按功能分文件
# user.py
# order.py
# payment.py
# 10人团队:按模块分目录
# users/
# orders/
# payments/
# 50人团队:可能需要微服务
# user-service/
# order-service/
# payment-service/
# 团队增长驱动架构演化
演化式架构的原则
原则1:从最简单的可行方案开始(YAGNI)
You Aren't Gonna Need It
# ❌ 过度设计
class AbstractDataAccessLayer(ABC):
@abstractmethod
def execute_query(self, query: Query) -> Result: ...
class SQLDataAccessLayer(AbstractDataAccessLayer):
def execute_query(self, query: Query) -> Result:
# 100行代码实现通用查询抽象
...
# ✅ 够用就行
def get_users():
return db.query(User).all()
# 等真正需要多个数据源时再抽象
原则2:等待三次重复再抽象
# 第1次:写具体代码
def send_welcome_email(user):
smtp.send(user.email, "Welcome", "...")
# 第2次:发现类似需求,先复制
def send_reset_password_email(user):
smtp.send(user.email, "Reset Password", "...")
# 第3次:现在可以抽象了
def send_email(user, subject, template):
smtp.send(user.email, subject, render_template(template))
# 三次才能看清真正的模式
原则3:保持架构的可逆性
# 可逆的决策:容易改变
# - 使用 SQLite 还是 PostgreSQL?
# - 文件存本地还是 S3?
# - 同步还是异步?
# 不可逆的决策:难以改变
# - 选择编程语言
# - 单体还是微服务
# - 关系型还是文档型数据库
# 策略:尽量推迟不可逆决策
架构演化的反模式
反模式1:为未来设计
# ❌ "我们未来可能需要支持多租户"
class User:
tenant_id: int
shard_key: str
# ... 复杂的多租户逻辑
# 问题:
# - 你现在只有1个客户
# - 多租户增加了巨大的复杂度
# - 可能永远用不上
# ✅ 先做简单的
class User:
id: int
name: str
email: str
# 等真正有多租户需求时再重构
反模式2:追随潮流
# ❌ "大家都在用微服务,我们也要用"
# 5人团队,10个微服务
user_service.py
order_service.py
payment_service.py
notification_service.py
# ... 运维噩梦
# 问题:
# - 团队小,通信成本高于收益
# - 运维复杂度激增
# - 调试困难
# ✅ 根据实际情况选择
# 5人团队:单体应用,清晰的模块化
# 50人团队:考虑微服务
反模式3:一次性大重构
# ❌ "我们要把整个系统重写成新架构"
# 6个月后:
# - 老系统还在运行,积累新bug
# - 新系统还没完成
# - 业务需求变化,新架构已过时
# ✅ 渐进式重构
# 第1个月:重构用户模块
# 第2个月:重构订单模块
# 第3个月:重构支付模块
# 新旧系统共存,逐步迁移
演化式架构的实践
实践1:监控驱动演化
# 监控告诉你真正的瓶颈
import time
from functools import wraps
def monitor(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
duration = time.time() - start
# 记录性能指标
metrics.record(f'{func.__name__}.duration', duration)
if duration > 1.0:
# 真正的慢查询,需要优化
logger.warning(f'{func.__name__} took {duration}s')
return result
return wrapper
@monitor
def get_user(user_id):
return db.query(User).get(user_id)
# 基于监控数据决定哪里需要优化
实践2:Feature Toggle
# 使用开关逐步推出新架构
class FeatureFlags:
USE_NEW_PAYMENT_SERVICE = False
USE_REDIS_CACHE = False
def process_payment(order):
if FeatureFlags.USE_NEW_PAYMENT_SERVICE:
# 新架构
return new_payment_service.process(order)
else:
# 旧架构
return old_payment_logic(order)
# 可以安全地实验和回滚
实践3:Strangler Pattern(勒杀模式)
# 逐步替换老系统
# 路由层
def handle_request(request):
if request.path.startswith('/api/v2/users'):
# 新系统
return new_user_service.handle(request)
else:
# 老系统
return legacy_system.handle(request)
# 新功能用新架构,老功能保持不变
# 逐步迁移,不影响业务
对使用 AI 的程序员的建议
AI 的常见问题
问题1:倾向过度设计
# AI 可能生成
# "请帮我设计一个用户系统"
class UserRepository(ABC):
@abstractmethod
def find_by_id(self, id: UUID) -> Optional[User]: ...
class UserService:
def __init__(self, repo: UserRepository, cache: CacheProvider,
event_bus: EventBus, logger: Logger):
# 复杂的依赖注入
...
class UserController:
# 完整的MVC架构
...
# 问题:你只是想保存一个用户名和邮箱
问题2:不考虑演化路径
# AI 直接给你"最终架构"
# 没有告诉你从简单到复杂的演化路径
# 应该改成
# 阶段1:最简单的实现
# 阶段2:添加数据库
# 阶段3:提取服务层
# 阶段4:添加缓存
如何改进
提示词策略:
❌ 不好的提示:
"设计一个完整的电商系统架构"
✅ 好的提示:
"设计一个电商系统,要求:
1. 第一阶段只需要支持用户下单
2. 从最简单的实现开始
3. 说明未来如何演化到支持高并发
4. 不要过度设计,YAGNI原则
5. 给出每个演化阶段的触发条件"
审查清单:
真实案例
案例1:Twitter 的架构演化
2007年:Ruby on Rails 单体应用
- 足够简单,快速开发
2009年:性能问题
- Fail Whale 频繁出现
- 开始用 Scala 重写核心服务
2011年:微服务化
- 按功能拆分服务
- 引入消息队列
2015年:进一步优化
- 自研缓存、存储系统
教训:
- 不是一开始就设计完美架构
- 每次演化都是响应真实问题
- 渐进式改进,不是一次性重写
案例2:GitHub 坚守单体应用
至今仍是 Rails 单体应用
为什么?
- 团队熟悉
- 业务逻辑紧密耦合
- 通过其他方式优化性能(缓存、数据库分片)
教训:
- 不需要追随微服务潮流
- 单体应用也能支持大规模用户
- 架构选择取决于团队和业务
检查清单
开始新项目时,问自己:
总结
架构不是设计出来的,是长出来的:
- 从最简单开始——YAGNI,不为未来过度设计
- 真实压力驱动演化——性能数据,不是假设
- 等待模式出现——三次重复再抽象
- 渐进式改进——不要一次性大重构
- 保持可逆性——推迟不可逆的重大决策
记住:
今天的完美架构,可能是明天的技术债。
好的架构能随需求演化,而不是一成不变。
最好的架构是刚好够用的架构。

浙公网安备 33010602011771号