Fix canvas transfer timeouts and move images out of snapshots
This commit is contained in:
@@ -23,3 +23,49 @@
|
||||
- 生产构建在临时副本进行,不改动当前开发服务器产物。最终执行结果记录于 VALIDATION.md。
|
||||
|
||||
本轮没有真实登录会话的公网前后对照,也没有浏览器视觉/手感验收,因此不能给出“线上打开从 11.4 秒降至某个时间”的结论。若更新后仍等待数秒,应结合 Network 中 Server-Timing 的 upstream 值、响应体下载时间和体积进一步追踪公网链路/后端;前端减少重复工作不等于消除了上游延迟。
|
||||
|
||||
## 2026-11-06:传输中断与误保存实测
|
||||
|
||||
旧 15 秒 deadline 同时约束响应头和整个响应体。流式响应先发出 200 后,正文仍可能被该 deadline 中断;此前客户端把 JSON 读取失败吞成 null,随后误报 invalid_canvas_snapshot。已改为响应头 15 秒、正文总计 90 秒、单次无数据等待 30 秒,并保留客户端取消。读取中断和 JSON 格式错误分别报告,不制造空快照。
|
||||
|
||||
`[canvas-transfer]` 只记录 trace_id、资源路径、毫秒、字节数、chunk 数、结果/错误类型;不记录令牌、Cookie、节点内容或图片数据。first_chunk_ms 为收到响应头后到首段正文的时间;transfer_ms 为代理消费正文的时间,包含链路和下游背压,不能独自区分网络节点。
|
||||
|
||||
用户真实父画布样本(约 477,400 字节,466 KiB):
|
||||
|
||||
| 样本 | 响应头前 | 正文 | 合计 | 结果 |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| e342dd5b | 707ms | 25.925s | 26.632s | 读到 364,538 字节后 ResponseAborted |
|
||||
| 000949da | 632ms | 32.119s | 32.751s | 完整 477,441 字节 |
|
||||
| e33e4a53 | 713ms | 1.951s | 2.663s | 完整 477,385 字节 |
|
||||
| 7b5e0787 | 956ms | 15.407s | 16.363s | 读到 282,618 字节后 ResponseAborted |
|
||||
| 4f77aafc | 657ms | 22.591s | 23.248s | 完整 477,385 字节 |
|
||||
|
||||
同一画布大小基本不变,正文平均吞吐从约 14.5 KiB/s 到约 239 KiB/s 波动。慢样本大部分时间在正文传输,而非页面路由(17–39ms)或首响应前。ResponseAborted 表示连接/消费端被取消,不能等同于我们设置的 TimeoutError,也不能仅凭它判定用户主动点击取消。开发热更新可取消旧请求,但具体请求的取消来源尚未证实。
|
||||
|
||||
子画布只返回 727 字节,正文约 1ms;首响应等待约 0.27–1.46s。未携带凭据的健康检查三个新连接样本:DNS 1.6–1.9ms、TCP 累计约 190–197ms、TLS 累计约 465–1,454ms、首字节累计约 723–1,842ms。健康检查只能作小响应链路基线,不能代替登录后的快照或 SQL 测量。
|
||||
|
||||
### 为什么只看页面也会 PATCH
|
||||
|
||||
实际浏览器 `[canvas-dirty]` 抓到多次仅 viewport=true,nodes=[]、edges=false 的保存。原保存器把视角变化与内容变化一同比较,因此平移、缩放也上传整个约 466 KiB 快照。已改为内容指纹决定是否 PATCH;只改变视角时保存在独立本机键中,不上传,也不产生内容恢复冲突。节点/连线发生真实修改时仍按版本保存完整快照。初始化的无来源视口回调、微小浮点差异和非用户尺寸测量均不作为服务器内容修改。
|
||||
|
||||
新的 `[canvas-save]` 样本中,客户端请求体读取 1.5–7.5ms、JSON 编码 1.6–2.1ms、上传到上游并等待响应头 334–1,440ms、响应体读取解析 0.6–0.8ms;请求约 477,370 字节。中间阶段包含上传、后端排队/SQL/提交和返回链路,前端不能进一步给出各自占比。
|
||||
|
||||
### 尚需服务端对照
|
||||
|
||||
- Core canvas GET 调用 lockMaterial,源码先对 workspace 行 FOR UPDATE,且事务延续到 reply 返回。这是可能的同空间排队点;当前慢请求首响应前不足 1 秒,不能将其当作 22–32 秒正文慢的已证实主因。
|
||||
- 需 ECS 本机与公网读取同一快照的分段对照,并记录数据库取数、JSON 编码、写响应耗时及出口/网关限速。Gitea 与 API 解析到不同 IP,不能把 Gitea 大文件测试冒充同服务器对照。
|
||||
- 上传源码仍支持将图片内嵌为 data URL,可能放大快照;该父画布的实际图片占比尚需只统计字节、不输出内容的检查。迁到 managed assets 可让结构与图片独立读取,但不得为此在打开页面时暗中发起修改。
|
||||
- 此次修复没有宣称公网传输速度已经稳定,也未修改 Core 或用户线上图片存储。
|
||||
|
||||
|
||||
## 同步服务端对照:2026-11-06 13:23 UTC
|
||||
|
||||
父画布 trace `1462ea3c`:13:23:04.973 → 13:23:21.652 UTC,首响应 219.8ms,正文 16,458.6ms,共 477,388 字节。服务端记录位于 `/tmp/endoleap-canvas-diag-20261106T131903Z`(只含计数、TCP 状态与聚合等待,不含 HTTP 正文/令牌)。
|
||||
|
||||
- 公网 TCP RTT 约 172ms,累计重传从 1 增至 31,拥塞窗口最低 2 个报文段,发送队列最高 138,240 字节;包丢失/重传导致 CUBIC 反复收缩窗口,解释了长正文传输和吞吐波动。
|
||||
- 内部 Core→Traefik 链路出现接收窗口背压,但最后完成约 481KB 的应用响应;不是数据库在逐字节生成 16 秒的数据。
|
||||
- 对齐窗口的 PostgreSQL 聚合记录没有持续 Lock 等待;只捕获一次约 154ms 的活动。只读 EXPLAIN ANALYZE 的本机快照体积计算执行 6.23ms、规划 11.4ms,不能将几十秒归因于该 SQL。
|
||||
- 同期 eth0 出口每秒约 14–62KB,无宿主队列丢弃增量;这不足以判定具体哪一段运营商或云端限速产生丢包,未擅自更改共享反代/内核网络配置。
|
||||
- 数据库聚合确认父图含 9 个节点、2 条边、2 张内嵌图片。JSON 文本约 477,646 字节,图片 src 合计 474,073 字符,约占 99.3%。原先设计让两张图片阻塞整张画布的数据读取。
|
||||
|
||||
修复采用普通 personal SaaS 附件模式:一份原始附件、一份按需显示预览,快照仅引用附件。前端添加真实附件上传及显式旧图迁移;Core PR #15 提供单一 1024px 预览、权限检查和有界缓存。原图不替换,AI 继续取原始内容。图片独立加载后,结构读取不再受两张完整图片的传输时间阻塞。生产部署和指定画布迁移后的实际字节数/时间须重测后记录,不能把预计缩减当作已完成实测。
|
||||
|
||||
Reference in New Issue
Block a user