fix: prevent QUIC heartbeat stalls and isolate TCP retransmission counters [CI] [SKIP TESTS]
ci/woodpecker/push/verify Pipeline was successful
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/dev-image Pipeline was successful

This commit is contained in:
justme committed 2026-10-20 18:23:31 +08:00
1 parent 0066a947da
commit 0fd38b2367
14 files changed
+299 -50

No files matched your search

@@ -70,14 +70,15 @@ public static class TcpInfo
}
/// <summary>
/// 一条连接上周期性的内核采样(<c>tcp_info</c> 流):每个采样一行 (ts, side, srtt, rttvar, cwnd, retrans_total, segs_out, bytes_acked)。
/// 一条连接上周期性的内核采样(<c>tcp_info</c> 流):每个采样一行 (ts, side, srtt, rttvar, cwnd, retrans_total, segs_out, bytes_acked, conn)。
/// 两端各采样自己的套接字:Probe 的重传反映上行方向,Agent 的重传反映下行方向(代理场景里大流量走这个方向)。
/// 累计计数器在 Backend 按 side 分别求差。
/// 累计计数器在 Backend 按 (side, conn) 分别求差;conn 是当前记录器内分配的连接编号,不包含网络地址。
/// </summary>
public sealed class TcpInfoRecorder
{
private readonly MonoClock _clock;
private readonly long _side;
private long _nextConnection;
public TcpInfoRecorder(StreamSpec spec, Side side, MonoClock clock)
{
@@ -96,6 +97,9 @@ public sealed class TcpInfoRecorder
return;
}
// A recorder survives reconnects, and listeners can briefly have more
// than one socket. Kernel counters belong to a socket, not just a side.
long connection = Interlocked.Increment(ref _nextConnection);
try
{
using var timer = new PeriodicTimer(interval, _clock.Time);
@@ -107,7 +111,7 @@ public sealed class TcpInfoRecorder
}
long key = Rows.Append();
Rows.SetRow(key, [_clock.NowUs(), _side, s.SrttUs, s.RttVarUs, s.Cwnd, s.TotalRetrans, s.SegsOut, s.BytesAcked]);
Rows.SetRow(key, [_clock.NowUs(), _side, s.SrttUs, s.RttVarUs, s.Cwnd, s.TotalRetrans, s.SegsOut, s.BytesAcked, connection]);
}
}
catch (OperationCanceledException)