Skip to content

docs(openspec): 慢后端韧性设计提案 | backend-slow resilience proposal - #76

Draft
370025263 wants to merge 1 commit into
mainfrom
openspec/backend-slow-resilience
Draft

docs(openspec): 慢后端韧性设计提案 | backend-slow resilience proposal#76
370025263 wants to merge 1 commit into
mainfrom
openspec/backend-slow-resilience

Conversation

@370025263

Copy link
Copy Markdown
Collaborator

OpenSpec 设计草案(讨论中)。仅新增 openspec/changes/backend-slow-resilience/,不动任何源码。openspec validate backend-slow-resilience --strict 通过。

动机 | Motivation

2026-07-10 内网生产事故:LLM/embedding 后端是公用共享服务(长期慢、排队是常态),出现「服务失联」——网页打不开、team client 全部 ReadTimeout,但进程活着、watcher 正常。

当天上午合入的 29ce2fe(事件循环解冻)已生效(主线程 ep_poll 正常),故障是新的一层GET /api/v1/team/syncdef 路由(api.py:469),FastAPI 丢进 anyio 40 线程池;其内部 encode_batch假批量(逐条串行、每条 60s,llm.py:291),单个 /sync 占一个线程数分钟。dashboard 静态页 //app.js 也全是 defrouter.py:57,62),与 /sync 共享同一个池 → 池满则网页打不开。现场 /proc dump:40 anyio + 4 watcher 线程全卡在网络 poll。client 侧无 jitter、无退避、不认 Retry-Aftercli.py:288 timeout=30、daemon.py:373),30s 整齐重试 → 僵尸线程只堆不减。

根因不是 bug,是设计缺口:把「后端一慢就长时间占用」的同步慢活放进共享请求线程池,且客户端无削峰。后端排队是常态,架构却把常态当异常承受。

方案 | Approach

设计约束:后端永远慢、永远排队是常态。目标:后端任意劣化时,服务可用性(网页、health、注册、upload)不受影响,仅推荐新鲜度降级。6 个 capability:

  1. stale-while-revalidate-sync(核心):/syncasync、立即返回上次画像快照,刷新入后台队列 + 独立 worker + 同 client coalesce 去重。
  2. embedding-hardening:真批量 API、统一 CapacityLimiter 出站并发上限、SHUTTING_DOWN 可打断、接入 rate_limit 桶。
  3. request-path-isolation:dashboard 静态/查询路由改 async/reindex 改后台任务 + 202 + 进度查询。
  4. retry-convergence:agno 外层 retries=3 × 内层 8 次相乘(最坏 ≈33 分钟)收敛为单层。
  5. client-load-shedding:tick jitter + 连续失败指数退避 + 识别 503/Retry-After
  6. resilience-observability:health 暴露线程池水位/队列深度/后端延迟,status 显示 tick 连续失败计数。

_tick 失败语义已确认安全(幂等全量重算、30s 自然重来、零丢失),故服务端拒绝/降级安全。

兼容性 | Compatibility

  • 旧 client × 新 serverSyncResponse/manifest 结构不变,只是从「阻塞数分钟」变「毫秒返回」,旧 client 纯获益;不认新 Retry-After 则退回既有幂等重来,安全。
  • 新 client × 旧 server:jitter/退避/Retry-After 识别是纯 client 行为,旧 server 不发这些头时分支不触发,完全兼容。
  • 无破坏性 wire 变更,允许灰度期新旧混跑。

文件 | Files

proposal.md / design.md(含 7 条 Decision + 兼容性 D7 + Open Questions)/ tasks.md(6 阶段骨架,按 Migration Plan 独立可合入)+ 6 个 specs/*/spec.md。不含源码改动。

🤖 Generated with Claude Code

内网 2026-07-10 事故:29ce2fe 解冻事件循环后,/sync 的同步 embedding 打满
anyio 40 线程池 → 网页/team client 全部连不上。提案把慢活移出请求路径
(stale-while-revalidate)、加固 embedding 通路、轻重隔离、收敛重试、client
削峰、补可观测。设计约束:后端永远慢是常态,可用性不得随后端劣化下降。

草案 PR,6 个 capability spec + proposal/design/tasks;openspec validate --strict 通过。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant