news 2026/4/14 5:32:51

工程架构认知(三):从传统Web系统到AI大模型驱动系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
工程架构认知(三):从传统Web系统到AI大模型驱动系统

AI时代的系统架构演进:从传统Web到大模型驱动系统

一、传统 Web 系统结构

一个典型的 Web 架构链路如下:

Client → CDN → Load Balancer → API Gateway → Application Server → Cache → Database

各层核心作用

层级作用典型技术
CDN静态资源缓存,将内容分发到离用户最近的边缘节点,降低首屏延迟Cloudflare、AWS CloudFront
Load Balancer将流量分发到多个后端实例,避免单点故障,提升可用性Nginx、HAProxy、AWS ALB
API Gateway统一入口,负责鉴权、限流、路由转发、协议转换Kong、APISIX、Spring Gateway
Application承载核心业务逻辑,处理请求并返回响应Express、NestJS、Spring Boot
Cache热点数据缓存,拦截重复查询,减少数据库压力Redis、Memcached
Database数据持久化,保证 ACID 特性PostgreSQL、MySQL、MongoDB

核心优化方向

  • 延迟优化:CDN 缓存静态资源、Redis 缓存热点数据,让请求在到达数据库之前就被拦截返回
  • 吞吐优化:通过 Load Balancer 实现横向扩展,增加实例数量即可线性提升处理能力
  • 可用性:多实例部署 + 健康检查 + 自动摘除故障节点,任何单点宕机不影响整体服务
  • 一致性:数据库事务保证数据正确性,缓存失效策略保证数据最终一致

传统 Web 的核心假设是:请求是短暂的。客户端发一个 HTTP 请求,服务端在毫秒级返回响应,连接随即释放。整个架构都围绕"如何在单位时间内处理更多短请求(QPS)"来设计。

二、AI 时代的大模型系统架构

AI 系统的本质变化:

从"短请求-响应" → “长连接 + 长任务 + 异步执行”

传统 Web 里一个请求 50ms 就结束了,但大模型的一次推理可能要 5 秒甚至 60 秒。如果还用同步模型,一个请求就会占住一个线程/连接几十秒,系统很快就会被拖垮。因此 AI 系统必须从根本上改变架构模型。

新一代架构模型

Client ↓ Connection Layer(WebSocket / SSE,负责"挂着"等结果) ↓ API / Orchestrator(接收请求,创建任务) ↓ Queue(任务排队,削峰填谷) ↓ Worker Pool(从队列取任务,控制并发) ↓ Model Layer(LLM / 图像 / 视频模型,真正干活的地方) ↓ Pub/Sub(结果产出后,广播通知) ↓ Connection Layer(找到对应用户的连接,推送结果) ↓ Client

这个架构的精髓在于:请求的发起和结果的返回走的是两条独立的路径。客户端发请求后不会傻等,而是通过长连接"挂"在那里,等 Worker 处理完后通过 Pub/Sub 把结果"推"回来。

三、架构核心变化(本质)

维度传统 WebAI 系统为什么变了
请求模型同步(请求-响应)异步(请求-排队-回调)模型推理耗时太长,同步会阻塞所有资源
生命周期毫秒级(50~200ms)秒/分钟级(1~60s+)LLM 的 token 生成是逐个的,本质上就慢
通信方式短连接(HTTP)长连接(WebSocket/SSE)需要持续接收流式输出,短连接做不到
核心瓶颈QPS(每秒请求数)连接数 + 任务调度效率瓶颈从"处理速度"转移到"等待管理"

一句话概括这个本质变化:传统 Web 优化的是"多快能处理完一个请求",AI 系统优化的是"同时能挂住多少个等待中的任务"。

四、关键瓶颈点分析

1. 长连接(WebSocket / SSE)

每个长连接都会占用服务端资源,不像短连接用完就释放:

  • 文件描述符(FD)耗尽:Linux 默认每个进程只能打开 1024 个 FD,每个连接占一个 FD。如果不调整ulimit,1024 个用户同时在线就会把服务打挂
  • 内存占用:每个连接需要维护读写缓冲区、状态信息,大约占 30~80KB。1 万连接就是 300MB~800MB 的内存开销
  • 单机连接上限:即使调大 FD 限制,受限于内存和 CPU 调度能力,单机通常在 1万~5万 连接就是极限。超过这个数就必须横向扩展

2. 模型调用瓶颈

模型调用是整个链路中最贵、最慢、最受限的环节:

  • 高延迟:GPT-4 级别的模型,一次完整响应通常需要 3~30 秒,复杂推理甚至超过 60 秒。这不是网络延迟,而是模型本身的计算时间
  • 强限流(Rate Limit):API 提供商会限制每分钟的请求数和 token 数。比如 OpenAI 的 GPT-4 可能限制 500 RPM(每分钟请求数),超了直接返回 429 错误
  • 高成本:GPT-4 的输入 $30/M tokens,输出 $60/M tokens。一个带上下文的对话一次可能消耗数千 token,成本是传统 API 调用的成百上千倍

3. 任务堆积(Queue Backlog)

当用户请求的速度(生产速度)超过 Worker 处理的速度(消费速度)时,队列会不断膨胀。这会导致:

  • 用户等待时间从秒级退化到分钟级(延迟爆炸)
  • 队列占用的内存/磁盘持续增长
  • 更早的任务排在前面,后来的用户体验急剧恶化

这就是经典的背压(Backpressure)问题:下游处理不过来,上游还在不停塞数据进来。

4. 流式输出压力

大模型的响应是逐 token 生成的,前端需要实时展示"打字机效果"。这带来独特的压力:

  • 高频 flush:如果每生成一个 token 就 flush 一次网络缓冲区,假设每秒生成 30 个 token,就是每秒 30 次网络写入
  • TCP 小包过多:每次 flush 发送的数据可能只有几个字节,产生大量 TCP 小包,触发 Nagle 算法延迟或产生网络开销
  • CPU 序列化压力:每次 flush 都需要将数据序列化(JSON 编码)、写入缓冲区、触发系统调用,高并发下 CPU 占用显著

5. 上下文成本(隐性瓶颈)

这是最容易被忽视但影响最大的瓶颈:

  • token 增长:多轮对话中,每轮都要把之前的对话历史作为上下文传给模型。10 轮对话后,上下文可能从 500 token 膨胀到 5000+ token
  • 成本线性增长:上下文越长,每次调用的费用越高。而且输入 token 也计费,相当于"重复为历史对话买单"
  • 延迟线性增长:模型处理更长的输入需要更多时间,用户会明显感觉到"对话越久,回复越慢"

应对策略包括:上下文摘要压缩、滑动窗口截断、关键信息提取后丢弃原文等。

五、瓶颈解决方案(核心)

1. 长连接(WS / SSE)解决方案

核心思想:连接层与执行层必须解耦。

传统架构中,处理请求的服务器同时负责维护连接。但在 AI 场景下,一个任务可能执行 30 秒,如果执行层还要负责维护连接,资源利用率极低。所以必须把"谁跟用户保持连接"和"谁去调模型干活"拆成两个独立的服务。

架构设计:

Connection Server(多节点,只负责维持连接) ↕ Pub/Sub(Redis / NATS,消息桥梁) Worker(任意节点,只负责执行任务)

关键技术点:

多连接节点(横向扩展):单个 Connection Server 大约能维持 1 万个长连接。需要支持 10 万用户同时在线?部署 10 台 Connection Server,前面用 Load Balancer 分流即可。每台只做连接维护,不做业务逻辑,所以非常轻量。

Pub/Sub 消息分发:Worker 处理完任务后,不需要知道用户连接在哪台 Connection Server 上。它只需要把结果publish到以userId为 key 的频道。所有 Connection Server 都subscribe了这个频道,持有该用户连接的那台服务器收到消息后推送给客户端。这就是"找人"的过程。

无状态连接层:Connection Server 不存储任何业务状态,不绑定任务执行。它只做两件事:接收客户端连接、将 Pub/Sub 的消息推送给对应连接。这意味着任何一台 Connection Server 挂了,用户重连到另一台即可,不会丢失任务进度(因为任务状态在 Worker 和 Queue 那边)。

心跳机制:长连接如果长时间没有数据传输,中间的网络设备(NAT、防火墙、代理)可能会主动断开。所以需要定期发送ping帧保活。通常每 30 秒一次心跳就够了。

连接控制:限制单个用户的最大连接数(通常 1~3 个),防止恶意用户或 bug 导致的连接泄漏耗尽服务端资源。

2. 模型调用解决方案

核心:队列 + Worker Pool(限并发调用模型)

用户请求 → Queue(排队等候)→ Worker Pool(取出任务,控制最大并发数为 N)→ 模型 API

并发控制:根据模型 API 的 Rate Limit 设定 Worker Pool 的最大并发数。比如 OpenAI 限制 500 RPM,你的 Worker Pool 就不应该超过 ~8 个并发(500/60≈8)。超出的请求在队列里等,而不是直接打到模型 API 被 429 拒绝。

Backpressure(背压):设定队列最大长度。当队列已满(比如超过 1000 个待处理任务),直接拒绝新请求并返回友好提示(“系统繁忙,请稍后重试”),而不是无限堆积导致所有人的延迟都变得不可接受。这是一个有损可控的策略——宁可拒绝少数人,也不能让所有人都卡住。

连接复用:Worker 调用模型 API 时,使用 HTTP Keep-Alive 和连接池复用 TCP 连接。每次调用都新建 TCP 连接的话,TLS 握手就要消耗 50~100ms,高频调用下这是不可忽视的开销。

3. 流式输出优化

错误做法:每生成一个 token 就立刻 flush 到客户端。假设每秒 30 token,就是每秒 30 次网络写入,大量 TCP 小包,效率极低。

正确做法:批量 flush。设定一个时间窗口(比如 50ms)或 token 数量阈值(比如每 5 个 token),攒够了再一次性 flush。用户感知的延迟只增加了 50ms(人类感知不到),但网络效率提升了一个数量级。

// 伪代码示意 buffer = [] timer = setInterval(50ms, () => { if (buffer.length > 0) { flush(buffer) buffer = [] } }) onToken(token) { buffer.push(token) if (buffer.length >= 5) { flush(buffer) buffer = [] } }

六、WebSocket vs SSE(重点对比)

核心区别

维度WebSocketSSE
通信方向双向(客户端和服务端都能主动发消息)单向(只有服务端能推送给客户端)
协议独立的ws://协议,通过 HTTP Upgrade 握手建立基于标准 HTTP,使用text/event-stream内容类型
复杂度高(需要处理握手、帧解析、心跳、重连)低(就是一个不关闭的 HTTP 响应,浏览器原生支持)
自动重连无(需要自己实现重连逻辑)有(EventSourceAPI 自带断线重连,还能通过Last-Event-ID恢复)
适用场景需要双向通信的强交互场景服务端单向推送的场景

AI 场景推荐

SSE(默认推荐)适用于大多数 AI 对话场景:ChatGPT 类对话、流式文本输出、单向数据流。原因很简单——AI 对话本质上就是"客户端发一个问题,服务端流式返回答案",这是一个单向推送模型,SSE 完全够用,而且实现成本远低于 WebSocket。

WebSocket适用于需要客户端频繁主动发消息的场景:实时打断生成(用户说"停,换个方向")、多 Agent 协作实时同步、高频双向交互(如协同编辑 + AI 辅助)。

关于"打断生成"

这是选择 WebSocket 还是 SSE 时最常被讨论的功能:

  • WebSocket 方案:在同一条连接上直接发送{ type: "cancel", taskId: "xxx" }消息,服务端立即收到并中止生成。延迟极低,体验流畅
  • SSE 方案:SSE 连接是单向的,客户端无法在上面发消息。需要额外发一个POST /api/cancelHTTP 请求来通知服务端。功能上完全可行,但多了一次 HTTP 往返,且实现上需要保证 cancel 请求能路由到正确的 Worker

结论:如果你的产品只需要基础的对话流式输出,用 SSE。如果需要打断、实时控制等复杂交互,用 WebSocket。

七、SSE 高并发瓶颈与优化

虽然 SSE 实现简单,但在高并发下同样面临挑战:

瓶颈分析

连接数限制:SSE 本质上还是一个不关闭的 TCP 连接,同样受 FD、内存的约束。浏览器对同一域名的 HTTP/1.1 连接数还有 6 个的限制(HTTP/2 下多路复用可以缓解)。

HTTP 长连接占用:SSE 连接会一直占住 Web 服务器的一个 worker/线程。如果用 Apache 这种每连接一线程的模型,几百个 SSE 连接就能把服务器打满。必须用 Nginx、Node.js 这种事件驱动模型。

代理缓冲问题:Nginx 等反向代理默认会缓冲响应体,等攒够一定量再转发给客户端。这会导致流式数据被"卡住",用户看不到实时输出。必须显式关闭缓冲。

flush 频率:和前面讨论的一样,过于频繁的 flush 产生大量小包。

重连风暴:网络抖动时,如果所有客户端同时尝试重连,会产生瞬时的连接洪峰,可能直接压垮服务端。

优化方案

关闭代理缓冲(Nginx 配置):

proxy_buffering off; X-Accel-Buffering: no;

这两行配置确保 Nginx 不缓冲 SSE 响应,数据到了就立即转发。

批量 flush:前面已经讨论过,每 50ms 或每 N 个 token flush 一次,而不是逐 token flush。

心跳保活:SSE 协议支持注释行作为心跳,格式是: ping\n\n。定期发送(每 15~30 秒)防止中间设备因超时断开连接。

重连退避(Exponential Backoff):客户端重连时不要立即重试,而是按指数退避:1s → 2s → 4s → 8s,加上随机抖动(jitter)。这样即使大量客户端同时断开,重连请求也会被分散到一个时间窗口内,避免雪崩。

连接分层:将 Connection Layer 独立部署为专门的服务,和业务逻辑服务分开。这样 Connection 服务可以选用最适合长连接的技术栈(如 Node.js),而业务服务可以用最适合业务逻辑的技术栈(如 Java/Python)。

八、不同层的技术选型(语言 & 框架)

Connection Layer(连接层)

技术适用场景理由
Node.js(推荐)大多数场景事件驱动、单线程非阻塞 IO,天然适合高并发连接。单进程轻松维持上万连接,配合wssocket.io库生态成熟
Go需要更高性能goroutine 模型天然支持高并发,内存占用比 Node.js 更低,适合连接数极大(10万+)的场景
Rust极限场景零成本抽象 + 异步运行时(tokio),单机可以推到百万级连接,但开发成本高,通常只在基础设施层使用

连接层的核心特征是IO 密集而非计算密集——它不做复杂计算,只是维持大量连接并转发数据。所以事件驱动模型(Node.js)或协程模型(Go)是最佳选择。

Orchestrator(调度层)

技术适用场景理由
Node.js(NestJS)快速迭代TypeScript 全栈统一,NestJS 提供了依赖注入、模块化等企业级能力
Java(Spring)大型团队Spring 生态成熟,适合需要复杂事务管理、微服务治理的场景

调度层的职责是:接收请求 → 验证参数 → 创建任务 → 写入队列 → 返回 taskId。逻辑相对简单,选型主要看团队技术栈。

Worker Layer(执行层)

技术适用场景理由
Python(首选)AI 相关任务AI 生态的绝对主力:LangChain、LlamaIndex、HuggingFace Transformers、向量数据库客户端等几乎都是 Python 优先。RAG、Embedding、Agent 编排等任务用 Python 开发效率最高
Node.js简单的 API 转发如果 Worker 只是调用外部模型 API 然后转发结果,Node.js 也能胜任

Model Layer(模型层)

  • 外部 API:OpenAI、Claude、Gemini 等。优势是零运维,按量计费;劣势是受 Rate Limit 约束,且数据离开了你的控制范围
  • 本地部署:需要 GPU 服务器,使用 vLLM、TGI 等推理框架。优势是完全可控,无 Rate Limit;劣势是成本高,需要 GPU 运维能力

中间件选型

类型推荐技术说明
Cache / PubSubRedis兼具缓存和发布订阅能力,单机十万级 QPS,AI 系统的标配
QueueBullMQ(Node.js 生态)/Kafka(大规模)BullMQ 基于 Redis,轻量好用;Kafka 适合日均千万级消息的大规模场景
网关Nginx反向代理、负载均衡、SSL 终止,配置灵活且性能优异

九、最终架构总结

连接层负责"挂着",Worker 负责"干活",队列负责"排队",Pub/Sub 负责"找人"

这四个角色的分工就是 AI 系统架构的精髓。每一层都可以独立扩展:连接多了加 Connection Server,任务多了加 Worker,流量波动大就加长队列缓冲。

本质变化

维度传统系统AI 系统
驱动模型请求驱动(来一个处理一个)任务驱动(来一个排一个,异步处理)
执行模式同步(请求线程等到处理完)异步(请求线程立即释放,结果异步推送)
优化焦点QPS(单位时间处理更多请求)连接管理 + 任务调度(挂住更多人,调度更多任务)

架构核心原则

解耦连接、任务、执行资源,让系统可以独立扩展

这是一切设计决策的根基。当你面对任何架构选择时,问自己:这个决策是在让系统更解耦,还是在引入耦合?解耦意味着每一层可以按自己的节奏扩展和演进,耦合意味着牵一发而动全身。

十、最终认知升级(重点)

当你评估一个 AI 系统的承载能力时,不要再问:

“QPS 能扛多少?”

要问:

  • 能扛多少并发连接?→ 决定了同时在线用户数的上限
  • 能处理多少并发任务?→ 决定了 Worker Pool 的吞吐能力
  • 队列是否可控?→ 队列长度是否有上限?是否有背压机制?延迟是否在可接受范围内?
  • 模型资源是否被合理利用?→ Rate Limit 是否被充分利用但不超限?是否有连接复用和缓存命中?
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 5:28:57

fft npainting lama快速体验:智能修复图片,让照片更干净

fft npainting lama快速体验:智能修复图片,让照片更干净 1. 引言 1.1 为什么需要图片修复工具 我们都有这样的经历:拍了一张完美的照片,却发现背景中有不想要的物体;或者找到一张老照片,上面却有划痕和污…

作者头像 李华
网站建设 2026/4/14 5:26:14

我在 Cursor 里接入了 Claude Code,三种方式实测告诉你哪个最好用

我在 Cursor 里接入了 Claude Code,三种方式实测告诉你哪个最好用 Cursor 用了快一年,日常写代码够用。但遇到跨文件重构、从零搭架构这类活,它的 Agent 模式经常半途而废——改了三个文件,漏掉第四个的类型定义,然后整…

作者头像 李华
网站建设 2026/4/14 5:23:12

SPI协议极简指南:5分钟搞懂CPOL和CPHA的四种组合模式

SPI协议极简指南:5分钟搞懂CPOL和CPHA的四种组合模式 第一次接触SPI协议时,最让人头疼的就是CPOL和CPHA这两个参数。它们决定了时钟信号的极性和相位,直接影响数据传输的时序。很多工程师在实际项目中遇到SPI通信失败的情况,往往就…

作者头像 李华
网站建设 2026/4/14 5:20:54

DeepSeek-R1-Distill-Qwen-7B推理效果实测:Ollama部署后的真实问答案例

DeepSeek-R1-Distill-Qwen-7B推理效果实测:Ollama部署后的真实问答案例 1. 模型概述与部署准备 1.1 模型技术背景 DeepSeek-R1-Distill-Qwen-7B是基于Qwen架构的蒸馏版本推理模型,通过强化学习训练和知识蒸馏技术优化而来。该模型在保持7B参数规模的同时…

作者头像 李华