Leadaxe:XHTTP 连接池的断路器把主动中断误判为流失败,健康连接会被逐出
在 LxBox 议题 148(XHTTP 传输不稳定、XMUX 连接被逐出)中,Leadaxe 逐条回应:`connection download closed: http2: response body closed` 不是失败,它由通用连接中继产生、只因分类函数不识别该 HTTP/2 哨兵值才记为 ERROR——实节点上六次成功请求每次各一条且无连接被逐出,WS 看着干净是因为走另一条被识别的关闭路径,「XHTTP 坏了」很大程度是日志假象,他们会修分类;`lx_idle_suspend` 只作用于 WireGuard/AWG 端点,对 XHTTP 无效;后台恢复的「re-syncing tunnel(heartbeat/streams were paused)」不碰隧道,其中的 heartbeat/streams 是应用自己的 UI 统计流,恢复时只重读 VPN 状态、重启 UI 定时器,不重装 TUN、不重载配置、不关闭连接,措辞有误导性,他们会再看。真正的缺陷在连接池:被 LxBox 自己拆掉的 XHTTP 连接(`interrupt_exist_connections: true` 每次切换都如此)会取消请求上下文,在途上传返回取消错误,而断路器把它计为一次流失败,连续三次就把健康的池内连接标记为 failing 并逐出、还要先退避;该断路器是他们自己的实现,上游 Xray 没有对应机制。同一服务器的六个 XHTTP 变体放进一个 urltest 因延迟接近而抖动,更易命中。建议先把 `interrupt_exist_connections` 设为 false、urltest 组只留一个 XHTTP 变体或把 tolerance 提到 200–300 ms;lx.4 到 lx.8 之间 XHTTP/xmux 代码未变,仅升级预计不修复,只是排除其它差异。
作者原文@LeadaxeThanks for the detailed report — the transport matrix and the urltest/selector layout were genuinely useful. Some findings from reading the code and running your setup (VLESS+XHTTP+REALITY under urltest inside a selector,
interrupt_exist_connections: true) against a live node.1.
connection download closed: http2: response body closedis not a failure. This line comes from the generic connection relay, not from the XHTTP transport. It is logged at ERROR only because the error-classification helper does not recognise the HTTP/2response body closedsentinel as a normal close. On a live XHTTP node here, every successful request (HTTP 204, six out of six) produced exactly one such ERROR line, with zero connection evictions. WS closes its body through a different path that is recognised, which is why it looks clean by comparison. So a large part of the "XHTTP is broken, WS is fine" impression is a logging artifact. We will fix the classification.2.
lx_idle_suspenddoes not apply to XHTTP. That mechanism only acts on WireGuard/AWG endpoints; an XHTTP outbound is never touched by the idle tick. Settinglx_idle_suspend: 30shas no effect on your XHTTP connections, so this can be ruled out.3. "Resumed from background — re-syncing tunnel (heartbeat/streams were paused)" does not touch the tunnel. The "heartbeat/streams" in that message are the app's own UI statistics streams, not HTTP/2 streams. On resume the app re-reads the VPN status, restarts a 20-second UI timer and re-subscribes its telemetry clients. It does not reinstall the TUN, does not reload the config and does not close any connection. The wording is misleading and we will look at it. The correlation you saw is most likely you returning to the app and generating traffic again.
4. There is a real defect, and it is in the connection pool. An XHTTP connection torn down by us (which is exactly what
interrupt_exist_connections: truedoes on every urltest/selector switch) cancels its request context. An upload request still in flight then returns a cancellation error, and the pool's circuit breaker currently counts that as a stream failure. Three of those in a row mark a perfectly healthy pooled connection asfailingand evict it, plus arm a backoff before a new one may be opened. We confirmed this in isolation. Note the breaker itself is ours (upstream Xray has no equivalent) — so this is our bug, not inherited behaviour.Your layout makes this much easier to hit than a normal one: six XHTTP variants of the same server sitting under one urltest have near-identical latency, so the auto-selection can flap, and every flap fires a batch of interrupts.
Things worth trying on your side, to confirm:
- set
interrupt_exist_connections: falseon both the selector and the urltest group;- keep a single XHTTP variant in the urltest group instead of six, or raise
tolerance(say 200–300 ms);- test one XHTTP node directly, with no selector and no urltest.
What would help us most:
- the full dump, specifically every
xhttp: xmux:line —opened connection,evicted connection (cause=...)and anybreaker tripped. Thecause=value is what separates our bug from a genuine reset by the server or the network;- the XHTTP node config without secrets:
mode,downloadSettings, thexmuxsection, and the urltesttolerance/interval;- whether you are actually losing traffic, or mainly seeing these ERROR lines in the log — that tells us which of the two problems above you are hitting;
- whether it reproduces on core lx.8 (you are on lx.4).
Note that nothing in the XHTTP/xmux code changed between lx.4 and lx.8, so upgrading alone is not expected to fix this — it just rules out other differences.