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 单体应用

为什么?

  • 团队熟悉
  • 业务逻辑紧密耦合
  • 通过其他方式优化性能(缓存、数据库分片)

教训

  • 不需要追随微服务潮流
  • 单体应用也能支持大规模用户
  • 架构选择取决于团队和业务

检查清单

开始新项目时,问自己:

总结

架构不是设计出来的,是长出来的:

  1. 从最简单开始——YAGNI,不为未来过度设计
  2. 真实压力驱动演化——性能数据,不是假设
  3. 等待模式出现——三次重复再抽象
  4. 渐进式改进——不要一次性大重构
  5. 保持可逆性——推迟不可逆的重大决策

记住:

今天的完美架构,可能是明天的技术债。

好的架构能随需求演化,而不是一成不变。

最好的架构是刚好够用的架构。

posted @ 2025-11-29 21:55  Jack_Q  阅读(0)  评论(0)    收藏  举报