Releases: npanel-dev/Daybreak
Release list
v1.0.13 — 吞吐修复:mux 单流窗口 256KiB→2MiB(单连接 17→140 Mbps)
吞吐修复:单连接从 ~17 Mbps 提到 ~140 Mbps
adb 进模拟器实测(走隧道 vs 直连)钉死了瓶颈:
| 场景 | 修复前 |
|---|---|
| 直连裸 TCP 单连接 | 253 Mbps |
| VPN 隧道单连接 | ~15-19 Mbps |
| VPN 8 并发聚合 | ~148 Mbps(极不均) |
有效窗口恰为 256 KiB(= mux 初始流窗口),单连接被 窗口 ÷ RTT 钉死:
256KiB ÷ ~120ms 隧道 RTT ≈ 17 Mbps。自适应扩窗实测很不可靠。
修复(同时需要客户端 SDK 与本节点都更新):
- mux 单流窗口 256KiB → 2MiB:单流立刻 ~140Mbps@120ms,不再依赖不稳的扩窗。
上下行对称受益。 - h2 服务端窗口 4/8MiB → 16/32MiB(与客户端对齐):解多流上行在一条载体上顶到
旧 4MiB 的瓶颈。 - relay 出站 set_nodelay:转发关 Nagle,省一个 RTT 的攒包延迟。
注意:下行吞吐主要由客户端 SDK 的窗口决定,故 SDK(AAR/.so)也必须一起更新。
升级
bash install.sh产物
| 文件 | 架构 |
|---|---|
dbk-node-x86_64-unknown-linux-gnu.tar.gz |
x86_64 / amd64 |
dbk-node-aarch64-unknown-linux-gnu.tar.gz |
aarch64 / arm64 |
v1.0.12 — 幽灵在线:确认根因(acceptor 挂起) + 锁定回归测试
幽灵在线:确认根因、锁定修复
v1.0.11 的线上诊断日志已钉死根因并验证修复有效。客户端跑完 fast.com 断开时,
4 条会话池一起收尾,日志显示:
reader 结束 ×4 ← 帧循环都正常结束
acceptor 自然结束 ×3 ← 3 条秒退
acceptor 宽限超时被中止 ×1 ← 第 4 条(承载下载中继那条)卡住,靠 2s 宽限中止
serve 返回 → 在线上报 0 ← 面板归零
根因:serve() = join!(reader, acceptor) 要两个都结束才返回。reader(帧循环)
在 carrier 关闭时结束,但 acceptor 靠 mux actor 结束才退,而 actor 在「某条流接收积压
无消费者、永不排空」时永久阻塞 → serve() 永久挂住 → 在线注销永不运行 → 幽灵。前三版
(v1.0.8/9/10)都在修 reader,全打偏;v1.0.11 改 serve() 才改对。
本版(v1.0.12):功能与 v1.0.11 一致,另外
- 补可复现的回归测试:还原成无限
join!时超时转红、有界宽限时通过(变异验证过),
彻底锁死这个修复; - 清理 v1.0.11 的逐会话诊断日志,只保留一条低频信号(真的中止卡住的 accept 循环时)。
升级
bash install.sh已在 v1.0.11 的韩国节点验证:断开后约 5 秒内归零(不再是 3 分钟)。
产物
| 文件 | 架构 |
|---|---|
dbk-node-x86_64-unknown-linux-gnu.tar.gz |
x86_64 / amd64 |
dbk-node-aarch64-unknown-linux-gnu.tar.gz |
aarch64 / arm64 |
v1.0.11 — 幽灵在线定位:serve() 有界化 acceptor + 生命周期诊断
定位版(诊断 + 有界化硬化)
前三版(v1.0.8/9/10)都在修 run_session_io(reader),但线上实证证明打偏了:
v1.0.10 已部署,客户端跑完 fast.com 断开后,节点侧入站连接=0(reader 已结束),
却仍上报「在线 1」逾 3 分钟、且残留 1 条出站中继 —— 说明 serve() 没返回、
OnlineGuard 没 drop、retire 没跑,卡点在 reader 之外。
本版做两件事:
serve()不再无限等 acceptor:serve()=join!(reader, acceptor)要两个都
结束才返回。reader(帧循环)在 carrier 关闭时结束,但 acceptor 靠 mux actor
结束才退,actor 在「接收积压无消费者」时可能永不结束、accept_stream永久阻塞,
把 serve() 永久挂住。现在 reader 结束后给 acceptor 一个**有界宽限(2s)**自然收尾,
超时即中止。健康会话亚秒级自然结束、无行为变化。- 三条低基数诊断日志:
reader 结束/acceptor 自然结束(或被中止)/serve 返回。
下次复现即可判定到底卡在 reader、acceptor 还是 serve 之后。
复测请求(关键)
升级后请再走一遍:连韩国 → fast.com → 断开 → 等 3~4 分钟。然后把这两段发我:
ssh root@3.36.107.43 "journalctl -u dbk-node --no-pager -n 200 | grep -E '会话IO|carrier:|在线上报' | tail -30"
ssh root@3.36.107.43 "cat /etc/daybreak/VERSION; ss -tnp | grep dbk-node | grep -c ESTAB"
日志会直接告诉我们:若在线归零了 → 本版修好了(卡的是 acceptor);若仍是 1,
日志里缺哪条(reader/acceptor/serve)就精确指出真正的挂点,我据此补最终修复 + 回归测试。
产物
| 文件 | 架构 |
|---|---|
dbk-node-x86_64-unknown-linux-gnu.tar.gz |
x86_64 / amd64 |
dbk-node-aarch64-unknown-linux-gnu.tar.gz |
aarch64 / arm64 |
v1.0.10 — 会话回收改用 Xray 式绝对空闲 deadline 模型
重构
会话回收改用 Xray 式绝对空闲 deadline 模型(参考 Xray-core ActivityTimer)
v1.0.8/v1.0.9 已修好幽灵在线的两个根因;本版按 Xray-core 的设计把服务端会话回收
重构成更直观、更难写错的模型,功能等价、更干净:
- 单一绝对空闲 deadline(= 最后一次入站 + idle_timeout),只被入站帧刷新;
下行出站不刷新(死载体上的下行会永久挂在 H2poll_capacity上,若它能刷新计时,
静默断开但仍有 FCM/浏览器下行的会话就永不回收)。到点即判定静默失效并回收。 - 载体写以 deadline 为上界:等价于 Xray「计时器到点关连接以解除挂起」,写挂过
回收点即解除——彻底消除「向死连接写永久阻塞把会话钉死」。 - 回收即
shutdown关连接,解除对端/中继侧任何挂起的读写。 - 保留服务端 Ping 探活:存活但空闲的客户端由 mux 回 Pong 刷新 deadline,不被误杀。
影响
- 客户端断开后(含仍有下行中继的情况),面板在线数在约 2~3 分钟内归零。
- 与 v1.0.9 功能等价,回收机制更清晰、状态更少、回收点直接由 deadline 决定。
升级
bash install.sh产物
| 文件 | 架构 |
|---|---|
dbk-node-x86_64-unknown-linux-gnu.tar.gz |
x86_64 / amd64 |
dbk-node-aarch64-unknown-linux-gnu.tar.gz |
aarch64 / arm64 |
v1.0.9 — 幽灵在线根因二:载体写永久挂起导致会话不回收
修复
面板在线数在客户端断开后一直不归零(幽灵在线)——根因二:载体写永久挂起
v1.0.8 修好了保活计时被下行重置的问题,但线上实测会话仍不回收。抓到更底层的根因:
- 现象:客户端断开后,节点侧没有一条入站连接到监听口,却仍攥着十余条出站
中继(含 Google FCM:5228),在线上报连续 7 分钟以上恒为 1。 - 根因:H2 载体的
poll_write在发送窗口耗尽时依赖poll_capacity;对端静默
消失后永不回WINDOW_UPDATE,poll_capacity便永久 Pending。下行中继(安卓
FCM 推送、浏览器长连接)先把发送窗口写空,客户端随后断开——此后任何一次载体写
(下行帧或保活 Ping)都永久挂起,把会话读写循环整个钉死:保活探测再也轮不到、
会话永不回收、每个上报周期都被当成在线。 - 修复:给服务端的载体写加超时上界。写在界内完不成即判定载体静默失效、结束
会话循环,让注销得以运行。健康客户端毫秒级排空窗口、永不触界;只连着不排空的
已死连接才被回收。客户端行为不变。
影响
- 客户端无论正常还是异常(强杀/断网)断开,且即便仍有 FCM/浏览器等下行中继,
面板在线数都会在约 2~3 分钟内归零。 - v1.0.8 只修了两个根因中的一个;本版补上第二个,两者叠加才是完整修复。
升级
bash install.sh产物
| 文件 | 架构 |
|---|---|
dbk-node-x86_64-unknown-linux-gnu.tar.gz |
x86_64 / amd64 |
dbk-node-aarch64-unknown-linux-gnu.tar.gz |
aarch64 / arm64 |
v1.0.8 — 修复静默断开会话残留为「幽灵在线」
修复
面板在线数在客户端断开后一直不归零(幽灵在线)
- 根因:服务端会话保活的探测计时被下行流量重置。此前每轮
select!迭代都
新建一次探测计时,任何一次出站(下行)都会把它清零。客户端静默断开(强杀
App、断网,未发 RST)但仍有下行中继在推数据(安卓 FCM 推送、浏览器长连接)时,
节点不停往已消失的载体写下行 → 计时永远被重置 → 保活永不触发 → 会话永不回收,
在线登记表里留下幽灵,每个上报周期都被当成在线。 - 修复:保活改用固定墙钟间隔触发,只有入站帧才算「对端还活着」,出站
不再重置计时;连续两个探测周期无任何入站帧即判定静默失效并结束会话。 - 会话结束后立即中止 relay,释放它占着的目标连接(FCM/浏览器长连接),不再堆积。
影响
- 客户端无论正常还是异常(强杀/断网)断开,面板在线数会在
空闲超时(120s) + 上报周期(60s) ≈ 3 分钟内归零。 - 此前 v1.0.5/v1.0.6 修的是「注销被 relay.await 阻塞」,本次修的是更隐蔽的
「保活被下行重置」——两者叠加才会让有下行中继的会话永久残留。
升级
bash install.sh产物
| 文件 | 架构 |
|---|---|
dbk-node-x86_64-unknown-linux-gnu.tar.gz |
x86_64 / amd64 |
dbk-node-aarch64-unknown-linux-gnu.tar.gz |
aarch64 / arm64 |
v1.0.7
变更
新增一条在线上报计数日志(诊断用,低基数、不记任何用户标识或 IP):
控制面:在线上报 N 个用户
用于在「面板显示的在线数与节点实际不一致」时,从节点侧直接确认本周期到底上报了
几个在线用户——区分「节点已注销、后端缓存未清」与「节点仍在上报」两种情况。
功能与 v1.0.6 完全一致,仅多这一条日志。
升级
bash install.sh产物
| 文件 | 架构 |
|---|---|
dbk-node-x86_64-unknown-linux-gnu.tar.gz |
x86_64 / amd64 |
dbk-node-aarch64-unknown-linux-gnu.tar.gz |
aarch64 / arm64 |
v1.0.6
修复(重要,建议立即升级)
修掉 v1.0.5 引入的一个回归:节点空闲、0 连接,面板却仍显示在线用户。
v1.0.5 把在线注销改成了 RAII 守卫、并放在守卫作用域末尾执行,而作用域末尾落在
relay.await 之后。当客户端存在空闲的目标长连接(典型如安卓的 Google 推送
FCM 通道——对端长期挂着不发数据)时,中继会阻塞在那条读上、relay.await 永久
不返回,于是守卫迟迟不析构、注销执行不到 → 幽灵在线。
现改为:会话循环 serve() 一返回就立即注销(不等中继收尾),时序与 v1.0.4
一致;同时保留守卫,覆盖「会话任务被取消 / panic」那条 v1.0.3~1.0.4 覆盖不到
的路径。两类幽灵(静默掉线、任务取消)现在都被堵住。
已在场的幽灵会随本次升级重启清空。
升级
bash install.sh配置保留、只换二进制。跑过 v1.0.5 的节点务必升级到本版。
产物
| 文件 | 架构 |
|---|---|
dbk-node-x86_64-unknown-linux-gnu.tar.gz |
x86_64 / amd64 |
dbk-node-aarch64-unknown-linux-gnu.tar.gz |
aarch64 / arm64 |
最低 glibc 2.28(Debian 10+ / Ubuntu 20.04+)。
v1.0.5
修复
修掉一类「幽灵在线用户」:节点空闲、实际 0 连接,面板却一直显示有人在线。
根因在会话生命周期:一条连接认证后即登记在线,只有会话循环返回后才注销
(retire)。而当会话任务被取消——面板下发画像变化触发监听重建、SIGHUP
热加载、或会话 panic——serve() 的 future 被直接丢弃,那行 retire 根本执行
不到,在线条目就永久留在登记表;节点每 60s 把它当成在线上报一次,面板持续显示。
v1.0.4 的服务端保活只覆盖「客户端静默掉线」,覆盖不到「任务被取消」这条路,所以
会出现「节点 0 连接、面板仍显示 1 在线」。
现将在线登记改成 RAII 守卫:登记返回一个守卫,其析构(Drop)时执行注销。
无论会话正常结束、被取消还是 panic,只要守卫离开作用域就必然注销——幽灵从
机制上不再可能产生。残留流量也在 relay 收尾之后一并结转,比原来的手动注销更准。
升级前遗留的幽灵会随节点这次重启清空;此后不再新增。
升级
bash install.sh配置原样保留,只换二进制并重启。建议所有开了 report_online 的节点升级——
这个泄漏对它们通用,只是要发生一次「监听重建/热加载」且当时有活跃会话才会触发。
本版累计包含(相对更早版本)
- v1.0.4:H2 服务端上行窗口 64KB→4MB(上行吞吐大幅提升)+ 扩窗内存预算调大;
- v1.0.3:服务端保活回收「静默失效但没收到 RST」的连接(防另一类幽灵)。
产物
| 文件 | 架构 |
|---|---|
dbk-node-x86_64-unknown-linux-gnu.tar.gz |
x86_64 / amd64 |
dbk-node-aarch64-unknown-linux-gnu.tar.gz |
aarch64 / arm64 |
最低 glibc 2.28(Debian 10+ / Ubuntu 20.04+)。
v1.0.4
本次优化
大幅提升「上行」吞吐。 此前 H2 载体的服务端从不设置流控窗口,沿用 h2 缺省的
64 KiB——整条隧道跑在一条 H2 流上,这个窗口就是上行(客户端→节点)的总窗口,
于是无论链路多快,上行都被钉死在约 8 Mbps(65ms RTT,与带宽无关)。
现将服务端上行流控窗口设为 4 MiB(连接级 8 MiB),单条流上行可达约 500 Mbps
(65ms RTT)。取值刻意比客户端(16 MiB)保守:服务端同时承载多条会话,且这个 h2
窗口不走 mux 的共享内存预算,最坏内存 = 窗口 × 并发会话数。
扩窗内存预算上调。 节点侧自适应扩窗的全节点共享内存池由 256 MiB 提到
1 GiB——它是扩窗内存的硬顶(与用户数无关),只在真正高速传输时按需支取、
空闲不占,为高带宽时延积链路留足峰值窗口余量。
重要:本次只改善「上行」,下行取决于客户端 SDK
隧道下行吞吐由客户端 SDK 的接收窗口决定,节点端已具备所需的一切。若客户端
使用的是 2026-08-19 之前构建的旧 SDK(接收窗口自适应尚未加入,固定 256 KiB),
下行仍会被钉在约 32 Mbps(65ms RTT)——这需要重新编译并下发 SDK 才能解决,
与本次节点发布相互独立。
内存提示(小内存节点)
节点扩窗预算现为 1 GiB(共享上限,非预分配,只在高速传输时按需支取)。面向内存
较大的机器(如 8 GB 的 c6in.xlarge,占比约 12%)。1–2 GB 内存的小节点在高并发
高速场景下可能吃紧,如有需要请反馈,可提供按机器内存自适应的版本。
升级
bash install.sh配置原样保留,只换二进制并重启。向后兼容:流控窗口是 wire 上动态协商的,本次改的
是取值而非线格式,新旧节点与新旧 SDK 可混连,不必锁步升级。
产物
| 文件 | 架构 |
|---|---|
dbk-node-x86_64-unknown-linux-gnu.tar.gz |
x86_64 / amd64 |
dbk-node-aarch64-unknown-linux-gnu.tar.gz |
aarch64 / arm64 |
最低 glibc 2.28(Debian 10+ / Ubuntu 20.04+)。