AI系统架构实战指南:从单体到混合架构的演进

前言:架构是业务和团队的映射

架构设计从来不是寻找"完美方案",而是在特定约束条件下做出最合理的取舍。

架构演进的本质: 每一步演进都解决了特定问题,也带来了新的复杂性。任何架构改进都要问自己:新增的复杂性是否带来了相应的价值?

一、架构演进的典型路径

graph LR A[单体架构] --> B[进程守护] B --> C[多机部署] C --> D[消息队列] D --> E[微服务] E --> F[Serverless] F --> G[混合架构]
阶段解决的问题引入的复杂性
单体初期快速开发耦合严重、部署麻烦
进程守护进程崩溃恢复资源监控
多机部署单点故障数据一致性、负载均衡
消息队列流量削峰、异步处理状态管理、监控难度
微服务团队协作、独立部署服务发现、分布式事务
Serverless运维减负、按需付费冷启动、调试复杂
混合架构场景化最优协调复杂度

二、单体架构:一切都很简单,直到出问题

2.1 单体的局限

// 单体应用的结构
/app
  /controllers    // 用户订单支付
  /models         // 用户、订单、支付
  /services       // 邮件通知
  /routes.js

问题:

  • 代码耦合严重,改一处影响多处
  • 部署麻烦,小改动要部署整个应用
  • 团队协作困难,多人修改同一代码库
  • 扩展性差,整体部署或不部署

2.2 什么时候需要拆分

评估标准:

维度单体够用考虑拆分
团队规模< 5 人5-20 人(>20 人必须拆分)
业务复杂度简单 CRUD业务逻辑复杂
流量规模小流量高流量
部署频率月级别日级别

不是所有系统都需要拆分,有时候单体架构更简单。

三、AI 系统架构的特殊性

3.1 AI 组件不是"听话"的服务

做 AI 系统架构和传统系统最大的不同:你不能假设所有组件都是"听话"的

LLM 调用有几个明显特点:

  1. 延迟不稳定:同样的请求,有时 500ms,有时 5 秒
  2. 并发限制严格:大多数提供商有严格的 rate limit
  3. 成本随用量线性增长:失败重试要真金白银

3.2 第一个坑:把 LLM 当成普通 HTTP 服务

# 错误做法:当成普通 HTTP 请求
async def query_llm(prompt: str) -> str:
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "https://api.openai.com/v1/chat/completions",
            json={"model": "gpt-4", "messages": [...]}
        )
        return response.json()["choices"][0]["message"]["content"]

测试环境跑了几天挺好,直到某天并发量突然翻倍,系统疯狂报错(Timeout、Connection 错误)。

正确做法:加调用管理层

class LLMCaller:
    def __init__(self, max_concurrent=5, timeout=30):
        self.semaphore = asyncio.Semaphore(max_concurrent)
        self.timeout = timeout

    async def call(self, prompt: str, retry=3) -> str:
        for attempt in range(retry):
            async with self.semaphore:
                try:
                    async with asyncio.timeout(self.timeout):
                        return await self._do_call(prompt)
                except asyncio.TimeoutError:
                    if attempt == retry - 1:
                        raise
                    await asyncio.sleep(2 ** attempt)  # 指数退避
                except httpx.HTTPStatusError as e:
                    if e.response.status_code == 429:  # Rate limit
                        wait_time = int(e.response.headers.get("Retry-After", 60))
                        await asyncio.sleep(wait_time)
                        continue
                    raise

3.3 第二个坑:检索和生成的边界

问题:

  1. 检索质量参差不齐
  2. 上下文长度爆炸
  3. 成本不可控

解决:加质量评估层

async def enhanced_query(query: str) -> str:
    # 快速检索
    docs = await vector_search(query, top_k=3)

    # 评估检索质量
    relevance = await assess_relevance(query, docs)

    if relevance < 0.5:
        # 质量不够,扩展检索
        docs = await vector_search(query, top_k=10)
        relevance = await assess_relevance(query, docs)

        if relevance < 0.3:
            # 还是差,走通用回答
            return await generic_llm_response(query)

    return await llm_summarize(query, docs)

核心认识:AI 系统里的组件之间不是简单的串联,而是需要有"中间层"来做质量评估和路由决策。

3.4 第三个坑:状态管理

用户反馈"为什么问同样的问题,答案每次都不一样"。

简单方案: 把对话历史存 Redis。结果 Redis 内存爆炸,上下文长度限制也很快到了。

正确做法:分级存储 + 对话摘要

async def chat_with_memory(user_id: str, message: str) -> str:
    # 获取最近对话
    recent_history = await redis.get(f"chat:recent:{user_id}")
    messages = json.loads(recent_history) if recent_history else []

    # 超过 10 轮,做摘要
    if len(messages) > 10:
        summary = await llm_summarize_history(messages[:5])
        messages = messages[5:]
        messages.insert(0, {"role": "system", "content": f"对话摘要:{summary}"})

    messages.append({"role": "user", "content": message})
    response = await llm_call(messages)
    messages.append({"role": "assistant", "content": response})

    # 只保留最近 10 轮
    await redis.set(f"chat:recent:{user_id}", json.dumps(messages[-10:]))
    return response

3.5 AI 系统架构的核心原则

  1. 不要把 AI 组件当成可靠服务:要做专门的适配层
  2. 组件之间需要"质量评估层":特别是在检索和生成之间
  3. 成本控制要内置到架构里:LLM 调用按次付费
  4. 状态管理要考虑上下文限制:做摘要和分级存储
  5. 监控和日志很重要:AI 的不确定性让问题定位更难

四、模型服务架构演进

4.1 单机时代

最初的模型服务架构:一台 8 卡 A100,部署 Flask 服务,Nginx 转发。

问题:

  • 显存泄漏(3 小时从 65% 涨到 98%)
  • 进程假死
  • 单点故障

4.2 进程守护 + 监控

# Supervisor 配置
[program:model-service]
command=/opt/conda/bin/gunicorn -w 4 -b 0.0.0.0:5000 app:app
autorestart=true
stdout_logfile=/var/log/model-service.log

Prometheus 监控 GPU:

from prometheus_client import start_http_server, Gauge
import pynvml

gpu_memory_used = Gauge('model_gpu_memory_used_mb', 'GPU memory', ['gpu_id'])
gpu_utilization = Gauge('model_gpu_utilization_percent', 'GPU util', ['gpu_id'])

def update_gpu_metrics():
    for i in range(gpu_count):
        handle = pynvml.nvmlDeviceGetHandleByIndex(i)
        mem_info = pynvml.nvmlDeviceGetMemoryInfo(handle)
        util = pynvml.nvmlDeviceGetUtilizationRates(handle)

        gpu_memory_used.labels(gpu_id=i).set(mem_info.used / 1024 / 1024)
        gpu_utilization.labels(gpu_id=i).set(util.gpu)

4.3 多机部署

upstream model_backend {
    server 10.0.1.10:5000 max_fails=3 fail_timeout=30s;
    server 10.0.1.11:5000 max_fails=3 fail_timeout=30s;
    least_conn;  # 模型推理是长连接任务
}

多机的坑:

  • 模型一致性:两台服务器模型版本必须完全一致
  • 负载不均:least_conn 只考虑连接数
  • 状态同步:复杂度大幅上升

4.4 消息队列:削峰填谷

graph LR A[用户请求] --> B[Web 服务] B --> C[Redis 队列] C --> D[Worker 1] C --> E[Worker 2] D --> F[模型服务器] E --> F F --> G[结果存储] G --> H[轮询服务]

异步架构的好处:

  • 流量削峰
  • 失败重试
  • 资源充分利用

新挑战:

  • 延迟增加(同步变异步)
  • 任务状态管理复杂
  • 监控难度上升

4.5 高可用架构

graph TB A[用户请求] --> B[LVS 负载均衡] B --> C[Web 节点 1/2/3] C --> D[Redis Cluster] D --> E[Worker 集群 K8s] E --> F[模型服务器组 1/2] F --> G[PostgreSQL 存储] G --> H[轮询服务]

关键设计:

  • 无状态设计:Web 和 Worker 都无状态
  • 故障隔离:组件间网络隔离
  • 自动恢复:K8s 健康检查 + Redis Cluster 故障转移
  • 可观测性:全链路监控

4.6 模型服务的坑

坑一:冷启动问题

模型加载需要 3-5 分钟。解决:预热机制,新 Pod 先加载模型再接收流量。

坑二:显存碎片

频繁推理导致显存碎片化。解决:定期重启 Worker + 显存整理。

坑三:请求超时

长文本推理可能几分钟。解决:调整 proxy_read_timeout

坑四:Redis key 没设 TTL

任务完成后 key 没过期,Redis 内存爆满。解决:所有 key 都要带 TTL。

五、Serverless 架构

5.1 什么时候选 Serverless

适合的场景:

  • 不规律流量(波动大、偶发峰值)
  • 事件驱动任务(文件上传、定时任务)
  • 轻量级 API(逻辑简单、执行时间短)
  • 快速验证想法

不适合的场景:

  • 长运行任务(超过 15 分钟)
  • 高性能需求(极低延迟)
  • 复杂状态管理
  • 合规要求严

5.2 冷启动:看不见的性能杀手

函数体量首次冷启动热调用闲置 10 分钟后
简单(~1MB)~300ms~10ms~350ms
中等(~10MB)~800ms~20ms~900ms
复杂(~50MB)~1500ms~30ms~1800ms

冷启动与热调用延迟差两个数量级。

优化策略:

  1. 保持热度:定时任务定期 ping 函数
  2. 预热:流量高峰前主动触发
  3. 优化代码:懒加载依赖
  4. 升级配置:增加内存(AWS Lambda 内存和 CPU 绑定)

5.3 连接池放在函数外部

import psycopg2
from psycopg2 import pool

# 全局连接池(关键!)
connection_pool = None

def get_connection():
    global connection_pool
    if connection_pool is None:
        connection_pool = psycopg2.pool.SimpleConnectionPool(
            minconn=1, maxconn=5,
            host=db_host, database=db_name,
            user=db_user, password=db_password
        )
    return connection_pool.getconn()

5.4 多云对比

指标AWS Lambda腾讯云函数阿里云 FC
P50 延迟45ms60ms50ms
P99 延迟350ms480ms420ms
错误率0.01%0.03%0.02%
冷启动频率12%18%15%

AWS 稳定性更好,但国内用户访问延迟会被网络抵消。

5.5 Serverless 的坑

坑一:本地与线上不一致

本地 Python 3.10,云函数 3.9,库的兼容性问题。解决:用 Dockerfile 确保环境统一。

坑二:超时设置太激进

设成 3 秒,第三方 API 慢就超时。解决:预留余量(10 秒),监控 P99.5。

坑三:忘了处理异步任务

第三方 API 卡 10 秒,函数超时但 API 请求还在继续。解决:明确超时和重试策略。

坑四:环境变量管理混乱

测试 API key 推到生产。解决:环境分离,不同配置文件。

六、AI 集成模式演进

6.1 模式一:简单调用

@app.post("/generate-summary")
async def generate_summary(content: str):
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[{"role": "user", "content": f"摘要:{content}"}]
    )
    return {"summary": response.choices[0].message.content}

问题:

  • API 调用慢(10-20 秒)
  • 成本不可控
  • 错误处理不够
  • Prompt 不稳定

6.2 模式二:异步调用

@app.post("/process-content")
async def process_content(content: str, background_tasks: BackgroundTasks):
    task_id = f"task_{int(time.time())}"
    redis.hset(f"task:{task_id}", mapping={"status": "pending"})

    # 后台异步处理
    background_tasks.add_task(process_with_ai, task_id, content)

    return {"task_id": task_id, "status": "pending"}

好处: 用户不用干等。 新问题: 任务状态管理复杂、用户需要轮询、缓存没做好。

6.3 模式三:分级模型选择

class AIModelSelector:
    def __init__(self):
        self.model_mapping = {
            "high_quality": {"model": "gpt-4", "max_tokens": 2000, "temperature": 0.3},
            "general": {"model": "gpt-3.5-turbo", "max_tokens": 1000, "temperature": 0.7},
            "fast": {"model": "gpt-3.5-turbo", "max_tokens": 500, "temperature": 0.5}
        }

    def select_model(self, task_type: str, priority: str = "normal"):
        if priority == "high":
            return self.model_mapping["high_quality"]
        if task_type in ["content_creation", "code_review"]:
            return self.model_mapping["high_quality"]
        elif task_type in ["summarization", "tag_extraction"]:
            return self.model_mapping["general"]
        else:
            return self.model_mapping["fast"]

效果: GPT-4 只占 10% 调用量,但处理最重要任务。成本下降 60%。

6.4 模式四:嵌入业务流程

AI 参与决策,不只吐一段生成内容:

class ContentAIWorkflow:
    async def process_content(self, content_id: int, content: dict):
        # AI 初步评估
        ai_assessment = await self._ai_pre_assessment(content)

        # 根据评估走不同流程
        if ai_assessment["risk_level"] == "high":
            await self._escalate_to_human(content_id, ai_assessment)
        elif ai_assessment["risk_level"] == "medium":
            additional_checks = await self._run_additional_checks(content)
            if additional_checks["passed"]:
                await self._approve_content(content_id)
            else:
                await self._escalate_to_human(content_id, additional_checks)
        else:
            await self._approve_content(content_id)

        # 记录反馈,持续优化
        await self._record_feedback(content_id, ai_assessment)

关键区别:

  • AI 参与决策,不只生成内容
  • 有反馈循环,定期分析准确率
  • AI 是"专家"不是"工人"

6.5 模式五:混合架构

graph TD A[内容提交] --> B{规则引擎} B -->|明确违规| C[直接拒绝] B -->|明确通过| D[通过] B -->|不明确| E{AI 评估} E -->|高风险| F[人工审核] E -->|低风险| D E -->|中风险| G{补充检查} F --> H{人工决策}

三层架构:

  • 规则引擎:处理明确规则(快、准)
  • AI:处理模糊判断(理解上下文)
  • 人工:处理边界情况(复杂决策)

效果: 审核准确率从 75% 提到 92%,人工审核量减少 80%。

七、分布式系统的挑战

7.1 数据一致性问题

def process_order(user_id, amount):
    inventory.reduce_stock(amount)       # 1. 扣库存
    order = order_service.create_order() # 2. 创建订单
    payment_service.charge(user_id)      # 3. 支付
    # 问题:如果支付失败,库存已经扣了

解决:Saga 模式(带补偿)

class CreateOrderSaga:
    def execute(self, user_id, amount):
        try:
            inventory_service.reduce_stock(amount)
            order = order_service.create_order(user_id, amount)
            payment_service.charge(user_id, amount)
            return order
        except Exception as e:
            # 补偿操作
            inventory_service.restore_stock(amount)
            raise e

7.2 服务发现

const consul = require('consul')();

// 服务注册
await consul.agent.service.register({
    name: serviceName,
    address: serviceUrl,
    check: {
        http: `http://${serviceUrl}/health`,
        interval: '10s'
    }
});

// 服务发现
const services = await consul.agent.service.list();

7.3 分布式追踪

from opentelemetry import trace

tracer = trace.get_tracer(__name__)

@tracer.start_as_current_span("process_order")
def process_order(order_id):
    with tracer.start_as_span("get_order"):
        order = get_order(order_id)
    with tracer.start_as_span("process_payment"):
        process_payment(order)

八、拆分策略

8.1 垂直拆分(按业务功能)

/user-service
  - 用户管理
  - 权限管理

/order-service
  - 订单处理
  - 订单查询

/payment-service
  - 支付处理
  - 退款管理

8.2 水平拆分(按流量)

/user-service-master
/user-service-slave-1
/user-service-slave-2

8.3 拆分的常见坑

坑一:过度拆分

把所有东西都拆成独立服务,管理复杂。解决:合并相关服务,减少服务数量。

坑二:数据拆分不清晰

导致数据访问复杂。解决:按业务域拆分数据,明确所有权。

坑三:监控困难

服务多了,监控变难。解决:分布式追踪 + 集中监控。

九、成本控制策略

9.1 成本控制要前置

不要等账单来了才发现成本爆了。从设计阶段就要考虑:

策略效果
分级模型选择GPT-4 只用于关键任务
结果缓存相似问题复用答案
Prompt 优化减少 token 消耗
本地预处理过滤低质量请求
批处理非实时场景合并请求

9.2 智能采样(影子部署)

SHADOW_RATES = {
    "low": 1.0,    # 低风险 100% 影子
    "medium": 0.5, # 中风险 50%
    "high": 0.2    # 高风险 20%
}

9.3 按场景分级

# 简单任务用便宜模型
def select_model(task_type):
    if task_type == "simple_qa":
        return "gpt-3.5-turbo"
    elif task_type == "code_generation":
        return "gpt-4"
    else:
        return "claude-3-5-sonnet"

十、监控与可观测性

10.1 全链路监控

# Prometheus 告警规则
groups:
- name: model_service_alerts
  rules:
  - alert: HighQueueLength
    expr: redis_queue_length{queue="model_tasks"} > 1000
    for: 5m
    labels:
      severity: warning

  - alert: ModelServiceDown
    expr: up{job="model-service"} == 0
    for: 1m
    labels:
      severity: critical

  - alert: HighGPUMemory
    expr: model_gpu_memory_usage_percent > 90
    for: 10m
    labels:
      severity: warning

10.2 关键监控指标

技术指标:

  • 延迟(P50、P95、P99)
  • 错误率
  • 吞吐量
  • GPU 利用率
  • 显存使用率

业务指标:

  • 准确率
  • 用户满意度
  • 任务完成率

成本指标:

  • API 调用量
  • Token 消耗
  • 计算资源消耗

十一、架构原则总结

11.1 核心原则

  1. 简单可靠:复杂度是工程师的最大敌人
  2. 可观测:没有监控就没有真相
  3. 能恢复:故障必然发生,关键是快速恢复
  4. 无状态优先:有状态带来复杂度
  5. 故障隔离:一个组件问题不扩散

11.2 AI 系统的额外原则

  1. 不要把 AI 当万能药:用它擅长的(理解、生成、分类)
  2. 从简单开始:先 API 调用,遇到问题再优化
  3. 监控和日志要到位:AI 行为不可预测
  4. 要有降级方案:AI 出问题不能拖垮系统
  5. 成本控制要前置:设计阶段就考虑
  6. AI 需要持续调优:不要指望一次完美

11.3 技术选型建议

场景推荐架构
快速原型单体 + API 调用
中等规模单机模型服务 + 监控
高可用需求多机部署 + 消息队列
流量波动大Serverless
复杂业务混合架构(规则 + AI + 人工)
隐私敏感本地部署

十二、写在最后

架构是业务和团队的映射。技术选型从来不是非黑即白。

几个核心体会:

  1. 没有"完美架构",只有"适合当前阶段的架构"
  2. 演进比革命好:渐进式改进,不要推倒重来
  3. 监控比功能重要:没有可观测性,所有架构都是黑盒
  4. 简单比复杂好:能用单体解决就别上微服务
  5. 成本是硬约束:技术方案要算经济账

做 AI 系统架构最大的不同:你不能假设所有组件都是"听话"的。它们有自己的脾气、限制和成本模型。传统系统关注"高效协作",AI 系统还要考虑"让不确定的组件协作得尽量稳定"。

接好了,AI 是系统里的一环;接不好,就是个慢且贵的外挂。


本文整合了 11 篇系统架构设计相关文章,涵盖单体到分布式演进、AI 系统架构、模型服务高可用、Serverless 实践、AI 集成模式、混合架构等核心技术。

版权声明: 本文首发于 指尖魔法屋-AI系统架构实战指南:从单体到混合架构的演进https://blog.thinkmoon.cn/post/ai-system-architecture-comprehensive-guide/) 转载或引用必须申明原指尖魔法屋来源及源地址!