# 一年前遇到的难题，被AI解决了

> 发布于：2026-06-02 | 分类：技术思考 | 原文：https://www.imbailey.cn/post/ai-solved-one-year-old-sse-problem

一年前实习的时候，mentor 让我做一个 Agent 问答前端。

这个前端本身并不复杂：用户输入一个问题，后端通过 SSE 流式返回 Agent 的执行过程，前端把这些过程一步步渲染出来。比如先展示“开始分析问题”，然后展示“拆分问题”，再展示“搜索资料”，最后展示“组合答案”。

听起来是一个很标准的 Agent UI。真正麻烦的是，SSE 在 API 测试工具里一切正常，请求总耗时大概 10 秒，每一秒都会有新事件返回；但一到前端就变得非常奇怪：前 9 秒页面什么都没有，最后 1 秒所有内容一股脑全部冒出来。

这就很离谱。

如果后端本来就是 10 秒后一次性返回，那很好理解。但问题是，用 API 测试工具直接请求后端，明明能看到事件一条一条回来。也就是说，后端看起来没问题，SSE 协议看起来没问题，只有前端页面不对劲。

## 当时的误判

我一开始怀疑是前端代码太臃肿。

当时的想法是：是不是每秒都有数据传来，但前端代码来不及消费？是不是 Vue 的状态更新太频繁？是不是消息列表渲染太重，导致浏览器主线程被阻塞？后来 mentor 和一个专门做前端的同事也一起看，大家又怀疑过 nginx gateway、后端网关、缓存、压缩、浏览器差异。

这些猜测都很合理，因为 SSE 这种东西一旦出问题，表现经常像玄学。你以为是渲染问题，可能是网络问题；你以为是后端问题，可能是代理问题；你以为是代理问题，又可能是某个响应头没配对。

我们捯饬了两周，最后也没彻底弄明白。

这件事就这么悬着了。

## 今天 Codex 找到了原因

今天我重新把这个问题丢给 Codex，让它看代码、看现象、写排查报告。它最后给出的结论是：问题不在 Vue，也不在后端，而在开发环境里的 Vite proxy。

更准确地说，当时前端请求并不是直接打到真实后端，而是先经过本地 Vite 开发服务器的代理，再转发到后端。普通接口这么做完全没问题，但 SSE 是流式响应，它对中间链路非常敏感。

这条链路里，早期的 SSE 事件没有立刻被浏览器收到，而是在代理层被缓冲了。于是后端其实已经一条一条发了，API 测试工具也确实能一条一条看到；但浏览器通过 Vite 代理访问时，前面的事件被攒住，等到响应头和后续数据一起释放，前端看到的就是“前面一直空白，最后突然全出来”。

这解释了一个当时很迷惑的现象：Answer 部分有时又能正常流式输出，所以看起来特别像前端渲染性能问题。但真正判断问题位置的关键，不是看页面有没有更新，而是看浏览器 Network 面板里的响应内容是不是逐步增长。

如果 Network 里响应本身就是一批一批出现，那就说明前端代码还没拿到数据，谈不上“消费不过来”。这时优化 Vue 渲染、减少状态更新、改组件结构，都只是在错误的位置努力。

## 解决方案

最后的解决方案反而很简单：让 Agent 的 SSE 接口绕过 Vite proxy，直接请求后端 API Host。

具体做法是给开发环境单独加一个 Agent API 地址，比如：

```env
VITE_APP_AGENT_API_HOST=http://真实后端地址
```

然后在接口层区分两类请求：

- 普通 HTTP 接口继续走原来的 Vite proxy，保持开发体验不变。
- Agent SSE 接口使用 `agentApiBase + '/local_doc_qa/local_doc_agent_chat'`，由 `fetchEventSource` 直接请求真实后端。

这样一来，中间少了一层会影响流式传输的开发代理，浏览器就能像 API 测试工具一样，实时收到后端发来的 SSE 事件。

这个修复并不炫技，但它非常关键。它把问题从“前端是不是太慢”重新定义成了“流式响应有没有被中间链路破坏”。

## 这件事给我的提醒

SSE 问题最怕只看页面表现。

页面不更新，不一定是组件没渲染；也可能是浏览器压根没收到数据。排查时至少要对比三条链路：

1. 直接请求真实后端，看 SSE 是否逐条返回。
2. 请求前端开发代理地址，看是否出现攒包。
3. 看浏览器 Network 里的响应内容，是逐步增长，还是最后批量出现。

只要真实后端正常、代理地址异常，基本就可以把注意力集中到代理、网关、压缩、缓冲、响应头这些中间环节上。

这也是我现在回头看这件事最大的感受：很多技术难题难的不是修复，而是定位。修复可能只改几行配置，但定位需要你知道应该怀疑谁、应该排除谁、应该看哪一个证据。

## AI 编程带来的变化

这次最让我感慨的，其实不是一个 SSE 问题终于解决了，而是 AI 编程正在改变程序员这份工作的重心。

以前我们经常要把大半个脑子装满繁杂的代码细节：这个库的 API 怎么写，那个代理的行为是什么，某个框架的边界条件在哪里，某段异步代码为什么没按预期执行。很多精力花在“记住”和“试错”上。

但现在，像 Codex 这样的 AI 工具已经可以读代码、跑命令、对比现象、写排查报告，还能把一个模糊的问题拆成可验证的假设。程序员不再必须亲自背下所有细节，更多精力可以放在业务设计、系统设计、算法设计，以及判断 AI 给出的结论是否可靠。

这几乎是在重塑程序员职业。

当然，这一定会让一部分只会 CRUD、只会照着需求打代码的人变得危险。因为如果工作内容只是把字段从数据库搬到页面上，把接口返回值塞进表格里，AI 确实会越来越擅长。

但程序员的价值从来不只是写代码。

理解业务、抽象问题、设计系统边界、判断方案取舍、和人沟通、处理不确定性、为长期维护负责，这些能力依然重要，而且很难被简单替代。AI 可以帮你写代码，但它还需要人告诉它什么值得写、为什么这么写、做到什么程度算对。

我很喜欢 ATM 和银行柜员这个例子。直觉上，ATM 能取钱、存钱、查余额，似乎应该消灭银行柜员。但 James Bessen 在 IMF 的文章 [Toil and Technology](https://www.imf.org/external/pubs/ft/fandd/2015/03/bessen.htm) 里提到，ATM 降低了单个网点所需的柜员数量，同时也降低了开设银行网点的成本。银行开了更多网点，柜员的角色也逐渐从重复点钞，转向销售、客户服务和金融产品介绍。

新技术往往不是简单地把人替换掉，而是把人推向新的任务。

AI 替你写代码，企业可能因此开发更多内部系统、更多 AI 应用、更多自动化流程。程序员也会从“代码打字员”转向“软件系统设计者 + AI 驯兽师”。

这件事让我觉得很兴奋。一个一年前三个人看了两周都没彻底解决的问题，今天被 AI 帮我重新拆开、定位、修复。它不是让我觉得程序员不重要了，而是让我更强烈地意识到：未来真正重要的，可能不是你记住了多少代码细节，而是你能不能提出好问题、判断好答案、设计好系统。

代码还要写，但写代码已经不再是全部。
