Skip to content

Releases: npanel-dev/Daybreak

v1.0.13 — 吞吐修复:mux 单流窗口 256KiB→2MiB(单连接 17→140 Mbps)

Choose a tag to compare

@EUForest EUForest released this 04 Sep 17:09

吞吐修复:单连接从 ~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 挂起) + 锁定回归测试

Choose a tag to compare

@EUForest EUForest released this 03 Sep 06:55

幽灵在线:确认根因、锁定修复

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 + 生命周期诊断

Choose a tag to compare

@EUForest EUForest released this 03 Sep 06:24

定位版(诊断 + 有界化硬化)

前三版(v1.0.8/9/10)都在修 run_session_io(reader),但线上实证证明打偏了:
v1.0.10 已部署,客户端跑完 fast.com 断开后,节点侧入站连接=0(reader 已结束)
却仍上报「在线 1」逾 3 分钟、且残留 1 条出站中继 —— 说明 serve() 没返回、
OnlineGuard 没 drop、retire 没跑
,卡点在 reader 之外。

本版做两件事:

  1. serve() 不再无限等 acceptorserve()=join!(reader, acceptor) 要两个都
    结束才返回。reader(帧循环)在 carrier 关闭时结束,但 acceptor 靠 mux actor
    结束才退,actor 在「接收积压无消费者」时可能永不结束、accept_stream 永久阻塞,
    把 serve() 永久挂住。现在 reader 结束后给 acceptor 一个**有界宽限(2s)**自然收尾,
    超时即中止。健康会话亚秒级自然结束、无行为变化。
  2. 三条低基数诊断日志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 模型

Choose a tag to compare

@EUForest EUForest released this 02 Sep 22:04

重构

会话回收改用 Xray 式绝对空闲 deadline 模型(参考 Xray-core ActivityTimer

v1.0.8/v1.0.9 已修好幽灵在线的两个根因;本版按 Xray-core 的设计把服务端会话回收
重构成更直观、更难写错的模型,功能等价、更干净:

  • 单一绝对空闲 deadline(= 最后一次入站 + idle_timeout),只被入站帧刷新;
    下行出站不刷新(死载体上的下行会永久挂在 H2 poll_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 — 幽灵在线根因二:载体写永久挂起导致会话不回收

Choose a tag to compare

@EUForest EUForest released this 02 Sep 21:10

修复

面板在线数在客户端断开后一直不归零(幽灵在线)——根因二:载体写永久挂起

v1.0.8 修好了保活计时被下行重置的问题,但线上实测会话仍不回收。抓到更底层的根因:

  • 现象:客户端断开后,节点侧没有一条入站连接到监听口,却仍攥着十余条出站
    中继
    (含 Google FCM :5228),在线上报连续 7 分钟以上恒为 1
  • 根因:H2 载体的 poll_write 在发送窗口耗尽时依赖 poll_capacity;对端静默
    消失后永不回 WINDOW_UPDATEpoll_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 — 修复静默断开会话残留为「幽灵在线」

Choose a tag to compare

@EUForest EUForest released this 02 Sep 20:30

修复

面板在线数在客户端断开后一直不归零(幽灵在线)

  • 根因:服务端会话保活的探测计时被下行流量重置。此前每轮 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

Choose a tag to compare

@EUForest EUForest released this 02 Sep 19:42

变更

新增一条在线上报计数日志(诊断用,低基数、不记任何用户标识或 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

Choose a tag to compare

@EUForest EUForest released this 02 Sep 19:21

修复(重要,建议立即升级)

修掉 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

Choose a tag to compare

@EUForest EUForest released this 02 Sep 18:59

修复

修掉一类「幽灵在线用户」:节点空闲、实际 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

Choose a tag to compare

@EUForest EUForest released this 02 Sep 16:57

本次优化

大幅提升「上行」吞吐。 此前 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+)。