☰
Hermes Agent:连接池参数怎么配,4 个指标验证调优生效
2026/11/4 6:28:01 网站建设 项目流程

Hermes Agent:连接池参数怎么配,4 个指标验证调优生效

凌晨 3 点告警:连接池打满,接口 P99 飙到 8 秒,日志刷满PoolTimeout。别急着拉大数字——Hermes Agent 的出站连接池和会话状态库是两处独立配置,这份指南直接给你能跑的参数和验证命令。

🔧 一份能直接跑的配置长什么样

连接池(预先开好一批连接反复用,省掉每次请求的握手开销)在 Hermes Agent 里分两块:出站 HTTP 池和 SQLite 会话库。下面这份配置摘录里,outbound段的值对应 agent/process_bootstrap.py 中httpx.Limits/httpx.Timeout的默认常量,state段对应 acp_adapter/session.py 初始化state.db的参数。

outbound: # LLM 提供商请求的出站连接池 pool: max_keepalive_connections: 20 # 空闲连接复用上限,多出来的空闲连接直接关闭 max_connections: 100 # 并发出站连接硬上限,超过的新请求排队等待 keepalive_expiry: 20.0 # 空闲连接回收秒数,必须小于反向代理的 30-60s 超时 timeout: connect: 15.0 # TCP 建连超时(秒),超时说明是网络层问题 read: null # SSE 流式场景不设读超时,别动 write: 15.0 pool: 10.0 # 从池里取连接的最长等待(秒),超时即 PoolTimeout state: # 会话状态存储,SQLite db: path: state.db # 位于 Hermes 主目录下的状态库 journal_mode: wal # 切到 WAL(预写日志,允许并发读写),并发必备 busy_timeout: 5000 # 锁等待毫秒数,防并发写时 "database is locked" monitoring: export: otlp: endpoint: http://collector:4318/v1/traces # OTLP 上报地址,验证指标全靠它 headers_env: Authorization: HERMES_OTLP_TOKEN # 取值放环境变量,配置里不写明文

⚠️ 别一上来把max_connections拉到 200:提供商侧的并发配额通常先扛不住,池子调大只会让 429 来得更快。

📊 不同规模下参数怎么选

数据库连接数计算没有标准公式,核心只有一件事:你的并发出站请求有多少,每条连接平均占多久。三档推荐值如下:

参数单机开发中小生产高并发集群
max_keepalive_connections52050
max_connections20100300
keepalive_expiry(秒)202020
timeout.pool(秒)51010
SQLite busy_timeout(毫秒)200050005000 + 只读副本
  • 单机开发:就你一个用户加几个会话,并发上限天然低,给 20 够用;不够用时问题立刻暴露,调优反而没意义。
  • 中小生产:100 是代码默认值,来源是"LLM 主调用并发 + 压缩、标题生成等后台任务"的叠加,keep-alive 20 约为它的五分之一,贴合常规 QPS。
  • 高并发集群:按节点数线性放大前先查提供商限流(并发数 / RPM);Dockerfile 里甚至写死了 SQLite 版本校验,因为集群规模下先崩的往往是 SQLite 而不是出站池。
  • keepalive_expiry 三档都锁死 20:这个值由反向代理的空闲超时(30-60 秒)约束,和你的规模无关。调大了,连接还没复用到就先被服务端掐断。

✅ 改完配置,怎么确认真的生效

改配置 ≠ 生效。出站参数目前硬编码在源码里,改完必须重启进程;OTLP 上报结构见 agent/monitoring/otlp_exporter.py(OTLP 即 OpenTelemetry 上报协议,span 指标经它进你的 Collector 可查),endpoint不配,下面一半指标看不见。

# 1) 确认源码常量已改且进程重启(预期输出新值 100) grep -n "max_connections" agent/process_bootstrap.py # 2) WAL 是否真的生效(预期输出 wal) sqlite3 state.db 'PRAGMA journal_mode;' # 3) 两类错误计数,调优后都应降到 0 grep -c "PoolTimeout" logs/gateway.log grep -c "database is locked" logs/gateway.log
指标验证什么在哪看
PoolTimeout 次数池耗尽是否解决上面命令 3,或日志面板
出站请求 P99延迟是否真降Grafana 查httpxspan 的 duration p99,对比改动前后
WAL 模式state.db 配置生效命令 2 输出wal
database is locked 次数并发写压力命令 3
gateway_health span 速率监控管道活着Collector 面板查该 span 每秒计数,应稳定

前两项下降、后两项归零,闭环完成。若 WAL 输出不是wal,先跑python -c "import sqlite3; print(sqlite3.sqlite_version)"——低于 3.51.3 的版本有 WAL-reset 上游 bug。

⚠️ 翻车场景速查

连接池超时设置和 SQLite 的坑大多重复出现,按现象对号入座:

现象根因修复动作
高峰后 10 秒起间歇PoolTimeoutmax_connections 偏小,或流式连接长时间不释放先查提供商并发配额,再上调到 150;仍耗尽则排查长占用连接
空闲后首请求报peer closed connectionkeepalive_expiry 大于代理空闲超时,复用了已被服务端关闭的连接keepalive_expiry 降到 20 秒,贴着代理 30 秒上限
并发写报database is locked还是默认回滚日志模式,读写互相阻塞设journal_mode: wal+busy_timeout: 5000
全部请求挂起但无报错timeout.pool 太大,把池耗尽掩盖成慢降到 5-10 秒快速失败,再查谁在占连接
部署后 state.db 异常、CPU 偏高旧版 SQLite 的 WAL-reset bug升级 SQLite ≥ 3.51.3,Dockerfile 已内置该校验

代码里对这些 sqlite 异常的处理路径可看 agent/insights.py,排查日志时优先搜OperationalError关键字。

一句话收束:出站并发设上限、在代理超时前回收空闲连接、池满时快速失败。默认值看 agent/process_bootstrap.py,效果盯上面 4 个指标。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询