1. 这不是画PPT,是给AI系统搭骨架
“图解AI应用架构设计”——这六个字一出来,很多人第一反应是打开Visio或draw.io,拖几个云朵、数据库、箭头,配上“大模型”“向量库”“API网关”几个标签,导出一张高大上的架构图发朋友圈。但真正做过三个以上落地AI项目的人都知道:那张图要是能直接当开发蓝图用,我早把键盘供起来了。
我带团队做过智能客服中台、工业质检平台、金融风控辅助系统,每次启动前最烧脑的环节不是写代码,而是把“用户说一句话,系统返回一个结果”这个看似简单的过程,拆解成可部署、可监控、可迭代的物理结构。所谓“图解”,本质是把模糊的业务意图翻译成工程师能执行、运维能保障、产品能理解的技术契约。它不解决“能不能做”,而解决“怎么稳、怎么快、怎么扛得住”。
这张图里藏着五个生死线:数据怎么进、模型怎么跑、状态怎么存、流量怎么控、故障怎么切。少画一根线,上线后就可能多花三天排查缓存击穿;漏标一个超时参数,高峰期就会出现请求堆积雪崩。它不是汇报材料,是开发说明书、运维检查表、成本核算单的三合一底稿。尤其现在大模型应用爆发,很多团队用LangChain搭个chain就上生产,结果QPS刚到50,Redis内存就爆了——问题不在模型,而在架构图里没画清“向量检索结果缓存该放在哪一层”。
适合谁看?如果你是技术负责人,需要快速判断一个AI需求是否具备工程化条件;如果你是算法工程师,总被问“为什么推理延迟忽高忽低”,这张图能帮你定位瓶颈在GPU调度还是网络IO;如果你是运维同学,看到“RAG流程”四个字就头疼,图解能告诉你哪些组件必须加熔断、哪些服务必须独立部署。它不教你怎么调参,但教你如何让调好的参数真正跑起来。
2. 架构图不是装饰画,是分层决策树
2.1 为什么必须分层?——从“一个Python脚本”到“百人协同系统”的必然路径
我最早做的AI项目,是个用Flask搭的文本分类接口:用户POST一段文字,后台调sklearn模型predict,return JSON。单文件,300行,连requirements.txt都懒得写。上线后老板说“加个历史记录功能”,我直接往SQLite里insert;说“支持图片上传”,我加了个PIL解析模块;说“要支持并发”,我改用Gunicorn起4个worker——直到某天凌晨三点,线上服务因OOM被kill,日志里全是“sqlite locked”报错,才发现所有请求都在抢同一个.db文件。
这就是不分层的代价。AI应用天然具备数据流长、状态耦合紧、资源异构强三大特性:
- 数据要经历清洗→向量化→检索→重排序→LLM生成→后处理,每步可能跨CPU/GPU/TPU;
- 用户会话状态、缓存键、向量索引、模型权重,存储介质和访问模式天差地别;
- 一个请求里既有毫秒级的向量相似度计算,又有秒级的LLM token生成,还有分钟级的异步批处理。
不分层,等于把火箭发动机、导航计算机、燃料泵全焊在一个铁皮箱里——点火时谁先炸都不知道。分层不是为了好看,是为了解耦:让数据工程师专注ETL管道优化,让算法工程师只关心模型精度,让SRE能单独扩容向量库而不影响API网关。
2.2 四层核心架构:每一层都踩过坑才定下来的边界
我们最终沉淀出四层架构(不是七层OSI那种理论分层,是实战中逼出来的物理隔离):
第一层:接入与路由层(Ingress & Routing)
核心任务:接住流量、识别意图、分流请求。
- 不是简单Nginx反向代理。比如用户问“查我上月账单”,要识别这是结构化查询,走SQL引擎;问“帮我写封道歉信”,才是典型LLM生成场景。我们用轻量级规则引擎(如Dagster的asset sensor)做初步路由,避免把所有请求都塞进LLM pipeline白白消耗GPU。
- 关键细节:必须实现请求指纹化。同一用户连续发“北京天气”“上海天气”“广州天气”,如果每次都重新向量化,向量库压力翻三倍。我们用MD5(用户ID+query)作为缓存key,命中率提升67%。
提示:别在这一层做复杂业务逻辑!曾有个团队在这里嵌入情感分析判断用户情绪再决定响应风格,结果CPU占用飙升40%,反而拖慢整个链路。情绪分析应该放到业务层异步处理。
第二层:编排与状态层(Orchestration & State)
核心任务:串联组件、管理上下文、兜底失败。
- LangChain的Chain看似方便,但生产环境里它把所有步骤绑死在一个Python进程里:向量检索失败,整个chain就卡住;LLM超时,重试逻辑得自己手写。我们改用Temporal工作流引擎,每个步骤(retrieve、rerank、generate)都是独立task,失败自动重试,超时强制终止,状态持久化到PostgreSQL。
- 关键细节:会话状态必须分片存储。早期用Redis全局存储用户对话历史,当用户量破万,Redis内存暴涨到80GB,GC停顿达2秒。后来按用户ID哈希分片到16个Redis实例,单实例内存压到3GB内,延迟稳定在5ms。
注意:千万别把LLM的system prompt硬编码在orchestration层!我们吃过亏——产品经理要改提示词,得重启整个工作流服务。现在prompt存在MongoDB里,通过版本号动态加载,热更新零 downtime。
第三层:能力原子层(Atomic Capabilities)
核心任务:提供单一、稳定、可替换的技术能力。
- 这层是真正的“能力超市”。比如向量检索能力,我们同时提供三种实现:
▪ Milvus(适合亿级向量、高精度)
▪ Qdrant(适合千万级、低延迟)
▪ Elasticsearch(适合带过滤条件的混合检索)
上层编排层通过统一接口调用,切换引擎只需改配置,不用动代码。 - 关键细节:每个原子能力必须自带健康探针。曾因Qdrant节点磁盘满导致检索失败,但orchestration层没收到异常信号,持续重试30分钟。现在每个能力服务暴露/health端点,包含磁盘使用率、向量索引加载状态、最近10次响应P99延迟,编排层据此自动剔除故障节点。
第四层:基础设施层(Infrastructure)
核心任务:屏蔽硬件差异、保障资源供给。
- 不是简单买GPU服务器。我们用Kubernetes+KubeRay管理大模型推理,但发现默认配置下GPU显存碎片化严重:一个7B模型占24GB显存,但集群里只剩两个12GB空闲块,新请求就排队。解决方案是启用NVIDIA MIG(Multi-Instance GPU),把A100物理卡切成4个独立GPU实例,每个实例显存隔离、算力独占。
- 关键细节:存储必须分冷热。用户上传的原始PDF文档(热数据)存在Ceph对象存储,高频访问的向量索引(温数据)存在SSD NVMe,而三年前的历史对话快照(冷数据)自动归档到AWS Glacier。成本降低38%,热数据读取延迟保持在20ms内。
2.3 分层不是教条,是动态平衡的艺术
分层边界会随业务演进移动。举个真实案例:
初期做智能法务助手时,“合同条款提取”是原子能力层的一个独立服务;随着客户要求增加“对比不同版本合同差异”,这个能力变得复杂,我们把它升级为独立微服务,迁入编排层——因为差异对比需要维护多版本文档状态,已超出原子能力范畴。
又比如,当用户量增长后,原本在接入层做的简单限流(令牌桶)不够用了,就把精细化限流(按用户等级、API类型、QPS阈值)下沉到基础设施层的Envoy网关,接入层只做基础路由。
分层的本质是责任划分:谁对延迟负责?谁对准确率负责?谁对成本负责?画架构图时,每根连接线都要标注SLA承诺值。比如“接入层→编排层”的P95延迟≤100ms,“编排层→向量检索服务”的成功率≥99.95%。没有SLA的架构图,就是一张废纸。
3. 图解关键组件:从“是什么”到“怎么选、怎么配”
3.1 向量数据库:不是选最快的,是选最不拖后腿的
向量数据库常被神化,其实它只是个“带相似度搜索的KV存储”。选型关键看三个指标:吞吐量、召回率、运维成本,且三者互斥。
我们实测过主流方案(数据来自2024年Q2内部压测,10亿向量,128维):
| 方案 | QPS(10并发) | Top10召回率 | 单节点成本 | 典型痛点 |
|---|---|---|---|---|
| Milvus 2.3 | 1,200 | 98.2% | $1,800/月 | 集群扩缩容需停服,索引重建耗时2小时 |
| Qdrant 1.9 | 2,400 | 96.5% | $900/月 | 不支持复合过滤(如“价格<100 AND 类别=电子”) |
| PGVector 0.5 | 350 | 94.1% | $300/月 | 高并发下PostgreSQL WAL日志暴涨,需专用备库 |
| Weaviate 1.23 | 800 | 97.0% | $1,200/月 | 文本分词器不可替换,中文支持弱 |
结论:Qdrant成为主力——不是因为它最快,而是QPS足够覆盖峰值,召回率损失在业务可接受范围(96.5%→98.2%仅提升1.7%,但成本翻倍),且运维最省心。我们甚至放弃Milvus的高召回率,因为法务场景中“漏检一条条款”比“多返回三条无关条款”后果更严重,而Qdrant的精确过滤能力(支持where filter)能规避大量误召。
配置要点:
- 索引类型选HNSW而非IVF:IVF需要训练聚类中心,数据分布变化时需重新训练;HNSW构建快,增量更新友好。我们每天新增10万向量,HNSW重建时间<30秒。
- ef_construction设为100,ef_search设为50:这是精度与速度的黄金平衡点。ef_construction过高(如200)会让索引构建时间翻倍;ef_search过低(如20)会导致召回率骤降。实测100/50组合下,P99延迟稳定在12ms,召回率96.5%。
- 务必开启disk-based storage:内存不足时自动落盘,避免OOM。我们设置
max_memory_map_size=20GB,单节点支撑5亿向量无压力。
实操心得:别迷信benchmark!我们曾按官网测试选了Milvus,结果上线后发现其Java SDK在高并发下线程池泄漏,每小时内存涨200MB。最后换回Qdrant的Rust原生客户端,内存恒定在1.2GB。选型必须跑真实业务Query,用线上流量镜像压测。
3.2 LLM推理服务:GPU不是越多越好,是越“专”越好
大模型推理有两大陷阱:显存浪费和计算空转。一个7B模型理论上只需14GB显存(FP16),但实际部署常占24GB以上——因为框架预分配、KV Cache、批处理padding全吃显存。
我们采用三级GPU资源池策略:
- 热池(Hot Pool):4×A10 24GB,运行7B/13B模型,支持动态批处理(Dynamic Batching)。请求进来先排队,等凑够8个再一起推理,GPU利用率从35%提到72%。
- 温池(Warm Pool):2×A100 40GB,运行34B模型,关闭动态批处理,固定batch size=2。大模型批处理收益递减,强行凑batch反而增加首token延迟。
- 冷池(Cold Pool):1×H100 80GB,只跑70B以上超大模型,且仅响应VIP客户请求。普通用户请求超时即降级到13B模型。
关键配置:
- FlashAttention-2必开:将7B模型的KV Cache显存占用从8GB压到3.2GB,实测首token延迟降低40%。
- PagedAttention替代传统Attention:类似操作系统虚拟内存,把KV Cache分页存储,显存碎片率从65%降到12%。我们用vLLM框架,配置
--block-size 32 --swap-space 16,16GB交换空间足够应对突发流量。 - 量化选AWQ而非GGUF:AWQ是权重感知量化,在7B模型上精度损失仅0.3%(用MT-Bench评测),而GGUF的INT4量化损失达2.1%。虽然AWQ加载慢15秒,但推理速度更快,长期看更划算。
踩坑记录:曾用TensorRT-LLM部署,启动快但不支持动态批处理。某次营销活动流量突增300%,GPU利用率瞬间飙到100%,新请求全部排队。换成vLLM后,动态批处理自动扩容batch size,P99延迟波动控制在±8ms内。
3.3 缓存体系:三层缓存不是炫技,是救命稻草
AI应用缓存失效是最大性能杀手。用户问“北京天气”,你缓存了答案;他两秒后问“上海天气”,缓存未命中——但这两个请求的向量相似度高达0.92!传统LRU缓存对此无能为力。
我们构建三层缓存:
L1:请求指纹缓存(Redis)
- Key:MD5(用户ID + query + model_version)
- Value:完整响应JSON
- TTL:30分钟(天气类信息时效性强)
- 效果:覆盖62%的重复查询,平均延迟从850ms降至12ms
L2:向量相似缓存(FAISS内存索引)
- 在GPU服务器内存中常驻FAISS Index,存储最近10万条query的向量及对应答案
- 新请求来时,先计算其向量,用FAISS找Top3相似向量,若相似度>0.85,直接返回对应答案
- 效果:额外覆盖23%的“语义重复”请求(如“今天北京热吗”vs“北京气温多少”),P95延迟再降180ms
L3:模型输出缓存(PostgreSQL)
- 存储LLM生成的结构化结果(如JSON Schema定义的字段)
- Key:query_hash + required_fields_hash
- 优势:即使模型升级,只要输出Schema不变,旧缓存仍可用;且支持SQL查询“过去24小时哪些query命中缓存最多”
独家技巧:给缓存加“衰减因子”。相同query第一次命中缓存返回100%置信度,第二次95%,第三次90%……到第10次强制刷新。避免缓存陈旧答案(如政策法规更新后,旧答案仍被反复返回)。
4. 实操全流程:从白板草图到生产上线的12个关键动作
4.1 动作1:用“三问法”校验架构图有效性
很多架构图画完就扔进Confluence,上线后才发现漏洞。我们强制执行“三问验证”:
- 问数据流向:“用户输入的一段文本,经过哪些组件?每个组件输出什么格式?谁负责序列化/反序列化?”
- 检查点:是否存在隐式转换(如Python dict ↔ JSON ↔ Protobuf),这些地方最容易出Unicode乱码或精度丢失。
- 问失败路径:“向量检索服务宕机时,请求会怎样?是直接报错500,还是降级到关键词搜索,或是返回兜底话术?”
- 检查点:每个外部依赖必须有fallback机制,且fallback的响应时间要计入SLA。
- 问扩展边界:“当前设计能支撑10倍流量吗?哪个组件最先成为瓶颈?扩容需要改几处代码?”
- 检查点:标注每个组件的水平扩展能力(如“API网关:支持K8s HPA自动扩缩”,“向量库:需手动分片,扩容耗时2小时”)。
4.2 动作2:绘制“血缘图谱”锁定关键依赖
架构图只画主干,血缘图谱画毛细血管。我们用Apache Atlas自动生成:
- 输入:所有服务的OpenAPI Spec、数据库Schema、K8s Deployment YAML
- 输出:可视化图谱,标出:
▪强依赖(实线):A服务宕机导致B服务不可用(如编排服务依赖向量库)
▪弱依赖(虚线):A服务慢影响B服务体验但不致瘫痪(如日志服务延迟)
▪隐藏依赖(红色波浪线):未声明但实际存在的耦合(如两个服务共用同一Redis DB,Key命名冲突)
上线前必须清理所有红色波浪线。曾发现“用户画像服务”和“推荐服务”共用Redis DB0,当画像服务批量写入导致Redis阻塞,推荐服务P99延迟从200ms飙到8秒——这种问题架构图根本画不出来,只有血缘图谱能揪出。
4.3 动作3:定义“最小可行架构”(MVA)
拒绝一步到位。我们坚持MVA原则:
- V1版只包含必要组件:接入层(Nginx)+ 编排层(Temporal单节点)+ 原子能力(Qdrant单节点 + 7B模型vLLM)+ 基础设施(K8s单Master)
- 砍掉所有非核心:不接Prometheus监控(用K8s自带metrics)、不配TLS(HTTP明文)、不设RBAC(全权限ServiceAccount)
- 目标:2小时内完成部署,能跑通端到端流程,P95延迟≤2秒
V1上线后,用真实流量压测,收集三类数据:
- 各组件CPU/内存/显存占用率(定位资源瓶颈)
- 请求在各环节耗时分布(定位延迟瓶颈)
- 错误日志中的高频Exception(定位逻辑缺陷)
V2版才基于数据加监控、加认证、加高可用。事实证明,80%的V1瓶颈在向量检索(占端到端延迟65%),而非LLM推理——这让我们把优化重心从GPU调优转向向量索引参数调优,节省两周工时。
4.4 动作4:编写“架构决策记录”(ADR)
每项关键选择必须留痕。模板如下:
## ADR-007:选择Qdrant而非Milvus作为向量数据库 **日期**:2024-03-15 **提出者**:张工(后端架构师) **状态**:已采纳 **背景**:法务合同分析需支持千万级条款向量,要求P95延迟<50ms,召回率≥95% **选项**: - Milvus:召回率98.2%,但集群扩缩容需停服2小时 - Qdrant:召回率96.5%,支持在线扩缩容 - PGVector:成本最低,但高并发下WAL日志溢出 **决策**:选用Qdrant,因业务可接受1.7%召回率损失,但无法承受停服风险 **依据**:压测报告显示Qdrant在1000QPS下P95=12ms,满足SLA;Milvus扩缩容停服违反SLO **后续行动**: - 配置Qdrant HNSW索引,ef_construction=100 - 开发召回率监控告警(低于95%触发)ADR不是形式主义。当新人问“为什么不用Milvus”,直接甩链接;当PM要求提升召回率,查ADR就知道当初妥协的底线在哪。
4.5 动作5:实施“混沌工程”验证韧性
架构图画得再美,不验证就是空中楼阁。我们每月做一次混沌实验:
- 网络层:用Chaos Mesh随机注入500ms网络延迟到编排层→向量库链路
- 存储层:kill Qdrant Pod,验证Temporal自动重试(3次)后降级到Elasticsearch
- 计算层:用nvidia-smi限制GPU显存至12GB,观察vLLM是否自动降级batch size
关键指标:
- 恢复时间(RTO):从故障注入到服务恢复正常≤30秒
- 数据一致性:故障期间丢失的请求≤0.1%(通过消息队列重放)
- 用户体验:P95延迟波动≤±15%(避免用户感知卡顿)
去年一次实验中,发现Temporal重试时未传递原始请求的timeout参数,导致重试请求超时时间翻倍。修复后,RTO从42秒压到18秒。
5. 常见问题与排查技巧实录:那些文档里不会写的真相
5.1 问题1:向量检索召回率突然暴跌,但Qdrant日志显示一切正常
现象:某天上午10点,合同条款检索召回率从96.5%骤降至72%,Qdrant metrics无异常,CPU/内存均正常。
排查路径:
- 查Qdrant
/collections/{name}/pointsAPI,确认索引数据量未突变(排除数据丢失) - 抽样对比“高召回”和“低召回”query的向量相似度——发现低召回query的向量L2范数普遍偏小(<0.3),而高召回query范数集中在0.6~0.8
- 追溯向量化服务日志,发现凌晨2点自动更新了sentence-transformer模型,新模型输出向量被L2归一化,旧模型未归一化
根因:向量库要求所有向量单位化,但新旧模型输出不一致,导致相似度计算失真。
解决方案:
- 立即回滚模型版本
- 在向量化服务加校验:
if np.linalg.norm(vector) < 0.4: vector = vector / np.linalg.norm(vector) - 建立向量质量监控:每日抽样1000条,统计向量范数分布,偏离阈值(0.5±0.1)即告警
实操心得:向量质量比数量重要十倍。我们现在线上每条向量入库前,必过三道校验:范数合规性、NaN检测、维度匹配。宁可丢弃1%脏数据,也不让一条错误向量污染整个索引。
5.2 问题2:LLM推理P99延迟忽高忽低,GPU利用率却始终70%
现象:vLLM服务P99延迟在200ms~2000ms间跳变,nvidia-smi显示GPU利用率稳定在68%~72%,显存占用恒定。
排查路径:
- 查vLLM日志,发现大量
[WARNING] Request xxx timed out, cancelled - 检查K8s Event,发现节点频繁发生
SystemOOM事件 - 登录节点,
cat /sys/fs/cgroup/memory/kubepods.slice/memory.usage_in_bytes—— 内存使用率达99%
根因:K8s节点内存不足,触发OOM Killer,vLLM进程被间歇性杀死重建,重建时需重新加载模型权重(耗时8秒),期间请求排队。
解决方案:
- 给vLLM Pod设置
memory.limit=32Gi(显存+内存预留) - 启用K8s
memory.swap(允许部分内存交换到SSD) - 关键:在vLLM启动参数加
--disable-log-stats,关闭实时统计日志(每秒写磁盘10MB,加剧IO压力)
独家技巧:GPU利用率≠计算效率。我们用
nvidia-ml-py3库监控nvmlDeviceGetUtilizationRates的gpu和memory两个指标:当gpu<50%但memory>90%,一定是内存瓶颈;当两者都高但延迟高,则是模型本身问题(如attention head过多)。
5.3 问题3:架构图里画了熔断,但服务雪崩时熔断器没生效
现象:向量库故障,API网关P99延迟飙升至15秒,熔断器配置failureRateThreshold=50%,但实际触发率仅20%。
根因分析:
- 熔断器统计的是HTTP状态码5xx比例,但向量库超时返回的是200+空JSON,被当成成功请求
- 熔断器采样窗口是10秒,而故障是渐进式(延迟从100ms→500ms→2000ms),10秒内失败率未达阈值
解决方案: - 改用响应时间熔断:
slowCallRateThreshold=30%(响应>500ms的请求占比) - 缩短采样窗口至2秒,快速响应延迟恶化
- 在向量库客户端加
@Timed注解,将超时异常(TimeoutException)映射为熔断器可识别的失败
血泪教训:熔断器不是保险丝,是精密仪表。我们现在线上所有熔断器都配双指标:失败率+慢调用率,并用Grafana看板实时监控熔断器状态(CLOSED/OPEN/HALF_OPEN),OPEN状态持续1分钟即触发告警。
5.4 问题4:架构图标注“支持灰度发布”,但灰度流量比例完全失控
现象:配置灰度规则“10%用户走新模型”,实际监控显示新模型流量占比32%。
根因:
- 灰度路由基于用户ID哈希,但用户ID是字符串,哈希分布不均(大量ID以“U100”开头)
- K8s Service的SessionAffinity设为ClientIP,导致同一IP下所有用户被路由到同一Pod,放大偏差
解决方案: - 改用MurmurHash3算法,对用户ID+时间戳哈希,确保均匀分布
- 灰度规则存入etcd,由Envoy统一读取并路由,避免各服务自行计算
- 每5分钟采样1000个请求,计算实际灰度比例,偏差>±2%自动告警
经验之谈:灰度不是功能开关,是概率实验。我们要求所有灰度发布必须同步开启A/B测试:新旧模型并行处理同一请求,用Jaccard相似度比对输出,确保效果提升才全量。曾有一次灰度显示准确率+0.5%,但人工抽检发现新模型回避敏感词过度,实际体验更差——数据不会说谎,但需要正确解读。
6. 架构图之外:让设计真正落地的三个隐形战场
6.1 战场1:成本治理——架构图里不画的钱,才是最大成本
架构图从不标注钱,但成本决定项目生死。我们建立三级成本看板:
- 资源层:GPU小时费、向量库存储费、带宽费(按TB计)
- 服务层:LLM API调用费(按token)、第三方服务费(如语音转文字)
- 隐性层:人力成本(运维巡检、故障处理)、机会成本(因延迟高流失的用户)
关键动作:
- GPU成本优化:用K8s Vertical Pod Autoscaler(VPA)自动调整vLLM Pod的resource.request,避免“13B模型申请40GB显存却只用24GB”。实测VPA将GPU闲置率从41%压到12%。
- 向量存储压缩:Qdrant支持
hnsw: {m: 16, ef_construction: 100}参数,m值越小存储越省,我们从默认16调到8,存储成本降35%,召回率仅降0.2%。 - 冷数据归档:对话历史超过90天自动转存至对象存储,成本从$0.023/GB降至$0.0012/GB。
真实体验:曾有个项目架构图完美,但月成本$28万,客户预算仅$8万。我们砍掉“实时语音转文字”(改用异步),将向量维度从768压到256(精度损失0.8%),用LoRA微调替代全参数微调——成本压到$7.2万,客户当场签约。
6.2 战场2:可观测性——没有监控的架构,等于没建
架构图里的“监控”二字,常被简化为“接Prometheus”。真实情况是:
- Metrics(指标):CPU/内存/延迟,但LLM的“推理延迟”需拆解为:排队时间+预填充时间+生成时间
- Logs(日志):vLLM的
INFO日志每秒数千行,必须用Loki+LogQL过滤关键事件(如cancelled request) - Traces(链路):用Jaeger追踪,但Span命名要规范——
vector_retrieve不能写成qdrant_call,否则无法聚合分析
我们强制要求:
- 每个组件暴露
/metrics端点,且指标名含业务语义(如ai_request_total{model="7b",status="success"}) - 所有错误日志必须带trace_id和request_id,支持跨服务追溯
- Tracing采样率动态调整:普通请求1%,错误请求100%,P95延迟>1s的请求100%
实战技巧:给架构图加“监控锚点”。在向量检索组件旁标注“监控项:qdrant_query_latency_seconds_bucket{le="0.05"}”,在LLM服务旁标注“监控项:vllm_generate_time_seconds_count{model="7b"}”。上线即同步配置Grafana看板,避免事后补监控。
6.3 战场3:演进机制——架构图不是终点,是起点
最危险的架构图,是画完就锁进Confluence再也不碰的。我们建立架构演进双周会机制:
- Review会:每两周,架构师带着最新架构图,对照线上指标(延迟、错误率、成本)讲解变更原因
- Retrospective会:每月复盘,用“5 Whys”分析重大故障:为什么熔断器没生效?→为什么只监控5xx?→为什么没定义慢调用?→为什么SLO没包含延迟?→为什么最初没把延迟当核心指标?
关键产出:
- 架构债务清单:如“Qdrant单节点部署,扩容需停服,预计Q3完成集群化”
- 技术雷达:评估新技术(如Ollama本地部署、Llama.cpp量化方案),标注适用场景和风险
- 演进路线图:明确V2版要解决的3个架构痛点,每个痛点关联具体指标(如“将向量检索P95延迟从12ms压到8ms”)
个人体会:画架构图最爽的时刻,不是完成时,而是三个月后看着线上指标曲线平稳下降,打开架构图发现当初画的那根线,真的成了系统的脊梁。它不性感,不炫技,但让AI真正从Demo变成产品——这才是架构师存在的意义。