
Onyx 如何用 ThreadHogUser 与 HealthProbeUser 压测调整 api-server 的 worker 与 threadpoolSize【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer当 api-server 同时处理大量长时运行的 agent 请求deep research、code interpreter 等流式聊天回合时每个请求会占住一个 anyio threadpool 线程直到回合结束。线程池被占满后 event loop 得不到调度Kubernetes 的 liveness 探针httpGet /healthtimeoutSeconds: 10、failureThreshold: 3开始超时pod 被 SIGKILL——这是 Onyx 文档中明确列出的生产失败模式。Onyx 仓库自带的 Locust 压测套件tools/loadtest/README.md提供了一对专门针对该失败模式的场景用户ThreadHogUser制造线程占用HealthProbeUser持续探测/health并记录失败率。本文的任务是用这两个用户跑一轮并发扫描在 Helm chart 的api.workers、api.threadpoolSize与 CPU 的组合中找到能让HEALTH:probe在你目标并发下保持 0 失败的最小配置。实验原理两个场景用户如何映射到生产故障ThreadHogUser指标前缀hog:*实现见 scenarios/thread_hog.py每个回合流式拉取一个故意很慢的 mock 响应默认模型mock-ttft1000-itl200-len600≈ 1s 600 × 0.2s ≈ 121 秒整个回合占住一个 threadpool 线程。它的思考时间ONYX_HOG_WAIT_SECONDS默认为 1 秒所以并发数-u几乎直接等于线程池压力。HealthProbeUser指标名HEALTH:probe实现见 scenarios/health_probe.py固定ONYX_HEALTH_PROBES默认 1个用户每ONYX_HEALTH_INTERVAL默认 1sGET 一次ONYX_HEALTH_PATH默认/health与-u无关这样聊天负载放大时探测节拍保持稳定。任何慢于ONYX_HEALTH_SLA_MS默认 10000即 liveness 的timeoutSeconds的探测记为失败失败原因形如slow 12000ms 10000ms SLA。HEALTH:probe的失败率就是本次实验的主要信号它在某并发下开始变非零说明该配置在这个并发下会开始被 liveness 杀掉。准备条件安装压测依赖。Locust 依赖在根项目可选的loadtest依赖组里默认不同步必须用uv run --group loadtest跑裸uv run会重新同步默认组并丢掉 Locustuv sync --group loadtest cd tools/loadtest启动 mock LLM server并在 Onyx 中注册。压测只测 Onyx 自身代码LLM 是可控依赖uv run --group loadtest uvicorn mock_llm.app:app --port 8001注册方式Admin Panel → LLM或PUT /api/admin/llm/providerprovider 类型必须填openai_compatible不能是openai后者会走 mock 未实现的 OpenAI Responses API 桥api_base指向 mock server如http://localhost:8001api_key 任意。ThreadHogUser 默认使用模型名mock-ttft1000-itl200-len600mock 的行为参数TTFT/ITL/长度就编码在这个模型名里litellm 会原样透传。创建 API key。由管理员通过POST /api/admin/api-key请求体{name: loadtest, role: basic}或 Admin Panel → API Keys 创建压测时作为ONYX_API_KEY传入。先跑一轮基线50 个长请求 全程健康探测ONYX_API_KEYkey ONYX_HEALTH_PATH/health \ uv run --group loadtest locust --headless -u 50 -r 5 -t 15m \ -H https://your-onyx-url ThreadHogUser HealthProbeUser其中key替换为第 3 步创建的 API keyyour-onyx-url替换为被测 Onyx 实例地址-u 50即 50 个并发长请求。跑完看 Locust 输出里HEALTH:probe的失败率为 0 表示 50 并发下该配置扛住了出现slow ...ms 10000ms SLA失败则说明这个并发度下 liveness 已经会开始失败。扫描 workers / threadpoolSize / CPU 组合单点运行只能说明一个配置行不行。找最小够用配置需要扫描。README 给出的扫描设计是并发长请求 ∈{10, 20, 40, 80}用ONYX_SHAPEstepramp阶梯式爬升而不是猜一个固定并发数对每一档并发遍历 chart 配置api.workers ∈ {1, 2, 4}×api.threadpoolSize ∈ {40, 80}× CPU∈ {2, 4}正确配置 HEALTH:probe在整个目标并发内保持 0 失败的最小配置。stepramp 模式的命令ONYX_RAMP_STAGES设为扫描用的四档并发ONYX_RAMP_DWELL为每档停留秒数ONYX_SHAPEstepramp ONYX_RAMP_STAGES10,20,40,80 ONYX_RAMP_DWELL300 \ ONYX_API_KEYkey ONYX_HEALTH_PATH/health \ uv run --group loadtest locust --headless -t 25m \ -H https://your-onyx-url ThreadHogUser HealthProbeUserONYX_SHAPEstepramp时形状参数会覆盖-u/-r。被测侧在 Helm values 中修改对应字段默认值与含义见 values.yaml 的api:段api.workers默认 1每个 uvicorn worker 是独立进程有各自的事件循环和线程池1增加并行容量也能避免单个卡死的 worker 拖垮整个 pod 的/health。chart 会在workers 1时给 uvicorn 启动命令追加--workers N见 api-deployment.yaml。api.threadpoolSize默认 0anyio 线程池大小服务包括流式聊天生成器在内的同步端点。0保持 anyio 默认值 40每个线程是真实线程文档要求按 CPU/内存来定大小。chart 将其渲染为容器环境变量ONYX_API_THREADPOOL_SIZE。api.resources文档特别指出 CPUlimit 必须明显高于 request——在并发慢流负载下1 核的 limit 会耗尽 CFS quota、拖住异步/health端点并引发 liveness kill。空闲 RSS 约 1.1Gimemory request 应保持在 1Gi 或以上chart 默认 request 1000m/1Gi、limit 3000m/3Gi。扫描 CPU ∈ {2, 4} 时同时调整 request 与 limit。每改一组 values 就重新部署 api-server再用同一套压测命令复跑记录该配置下HEALTH:probe首次出现非零失败的并发档位。结果判读与可选的 Prometheus 关联判读标准只有一条且来自文档HEALTH:probe失败率在你的目标并发下为 0。出现失败或探测超时被记为 exception就意味着该配置在该并发下会被 liveness 连续失败 3 次后杀 pod。在所有能通过的配置里选最小的一组workers / threadpoolSize / CPU 均最小。如果需要看资源侧的对应关系master 会在独立端口默认9646LOCUST_PROMETHEUS_PORT可覆盖的/metrics暴露locust_requests_total、locust_failures_total、locust_response_time_p95_milliseconds等指标配合导入 dashboards/chat-loadtest-correlation.json可以在一条时间线上叠加里程碑延迟、失败率与服务端 CPU/内存观察是哪个资源先饱和。注意 Prometheus Operatorkube-prometheus-stack不识别 pod annotation需要针对 metrics service 端口配 ServiceMonitor示例注释在 k8s/locust.yaml。限制与路由注意事项探测路径取决于目标指向LOCUST_HOST指向 web/nginx host 时/loadtest子路径会被 catch-all 路由遮蔽应指向专用 host 或 port-forward并把ONYX_HEALTH_PATH设为/api/health直接指向 api Service 时用/health是正确的。绝对数值不可跨环境比较文档以 st-dev 为例说明该环境是 direct-RDS绝对延迟数字与客户环境不同——不同 workers/threadpoolSize/CPU 配置之间应做相对比较而不是对某个绝对 SLA 下结论。探针路径不要混用/health/ready在线程池饱和时会报 not-ready适合 readiness/health只报告进程存活适合 liveness。values.yaml 明确警告不要把/health/ready放到 liveness饱和是负载诱导的、会同时命中所有副本按它重启会把一次变慢放大成服务中断。想改变单回合占用时长时用ONYX_HOG_MODEL换成带不同ttft/itl/len参数的 mock 模型名而不是改并发数ONYX_HOG_STREAM_READ_TIMEOUT默认 600s是单回合分块间最大等待121s 的默认回合时长远在阈值内。【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考