mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 17:10:43 +00:00
86 个采样点 / 约 1.5 小时:
QUIC: 最低 1 最高 8 平均 7.5
HTTP/2: 最低 1 最高 2 平均 2.0
QUIC 塌陷(<= 2 条)只有 2 次,占 2.3%
塌陷时 HTTP/2 一直是 >= 1 条(2/2 = 100%),归零 0 次
QUIC 连接数分布:
8 条 76.7%
7 条 15.1%
6 条 3.5%
5 条 2.3%
1 条 2.3% <- 塌陷(1.5 小时里约 2 分钟)
一次典型塌陷的时间线也记下来了(watchdog 日志):
重启把中断从「可能几分钟」缩到 26 秒。
目标「0 掉线」做不到 —— 4G 链路上 QUIC 会周期性塌陷。
但影响被压到 2.3% 的窗口,而且 HTTP/2 全程兜住。
教训:多行中文提交信息里有引号时,PowerShell 的 -m 参数会被吃掉。
一律写进文件再用 -F 提交。
130 lines
4.0 KiB
Python
130 lines
4.0 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
r'''分析连接数时间线 long2h_conns.tsv,找塌陷的规律。
|
||
|
||
目的:回答两个问题
|
||
1. QUIC 塌陷是不是周期性的?周期多长?
|
||
2. 塌陷期间 HTTP/2 那半边是不是一直活着?(这是双协议兜底的价值)
|
||
'''
|
||
from __future__ import annotations
|
||
|
||
from pathlib import Path
|
||
|
||
p = Path("/root/long2h_conns.tsv")
|
||
if not p.is_file():
|
||
print(" 没有 %s" % p)
|
||
raise SystemExit(0)
|
||
|
||
raw = p.read_text(encoding="utf-8", errors="replace").splitlines()
|
||
print(" 共 %d 行,前 3 行:" % len(raw))
|
||
for line in raw[:3]:
|
||
print(" %r" % line[:120])
|
||
print()
|
||
|
||
rows = []
|
||
for line in raw:
|
||
line = line.strip()
|
||
if not line:
|
||
continue
|
||
parts = line.replace(",", "\t").split("\t")
|
||
stamp = ""
|
||
nums = []
|
||
for x in parts:
|
||
x = x.strip()
|
||
if not x:
|
||
continue
|
||
if ":" in x and ("-" in x or len(x) <= 8) and not x.replace(":", "").isdigit():
|
||
stamp = x
|
||
else:
|
||
try:
|
||
nums.append(int(x))
|
||
except ValueError:
|
||
pass
|
||
if nums:
|
||
rows.append((stamp, nums))
|
||
|
||
if not rows:
|
||
print(" 解析不出数字")
|
||
raise SystemExit(0)
|
||
|
||
# 假设列是 [quic, h2] 或 [总连接, quic, h2] —— 按每行长度自适应
|
||
width = max(len(n) for _s, n in rows)
|
||
print(" 每行 %d 个数字(列)" % width)
|
||
print(" 前 5 行解析结果:")
|
||
for s, n in rows[:5]:
|
||
print(" %-12s %s" % (s, n))
|
||
print()
|
||
|
||
# 尝试识别:如果一行有 2 列,当作 [quic, h2];3 列当作 [total, quic, h2]
|
||
lower = [n for _s, n in rows]
|
||
if width == 2:
|
||
quic = [n[0] for n in lower]
|
||
h2 = [n[1] for n in lower]
|
||
elif width >= 3:
|
||
quic = [n[1] for n in lower]
|
||
h2 = [n[2] for n in lower]
|
||
else:
|
||
print(" 列数不支持")
|
||
raise SystemExit(0)
|
||
|
||
total = len(quic)
|
||
print(" ── 连接数统计(%d 个采样点)──" % total)
|
||
print(" QUIC: 最低 %d 最高 %d 平均 %.1f"
|
||
% (min(quic), max(quic), sum(quic) / total))
|
||
print(" HTTP/2: 最低 %d 最高 %d 平均 %.1f"
|
||
% (min(h2), max(h2), sum(h2) / total))
|
||
|
||
# 塌陷 = QUIC <= 2
|
||
collapse_idx = [i for i, q in enumerate(quic) if q <= 2]
|
||
print()
|
||
print(" ── QUIC 塌陷(<=2 条)──")
|
||
print(" 出现 %d 次,占比 %.1f%%" % (len(collapse_idx), len(collapse_idx) * 100.0 / total))
|
||
|
||
# 塌陷时 h2 还在吗
|
||
if collapse_idx:
|
||
h2_alive = sum(1 for i in collapse_idx if h2[i] >= 1)
|
||
h2_zero = sum(1 for i in collapse_idx if h2[i] == 0)
|
||
print(" 塌陷时 HTTP/2 >=1 条: %d 次(%.0f%%)"
|
||
% (h2_alive, h2_alive * 100.0 / len(collapse_idx)))
|
||
print(" 塌陷时 HTTP/2 也归零: %d 次" % h2_zero)
|
||
print(" -> 这就是双协议兜底的价值:%s"
|
||
% ("QUIC 塌了但 HTTP/2 还在扛" if h2_zero < h2_alive
|
||
else "两个一起塌,兜底没起作用"))
|
||
|
||
# 合并连续的塌陷区间,看周期
|
||
spans = []
|
||
start = None
|
||
for i, q in enumerate(quic):
|
||
if q <= 2 and start is None:
|
||
start = i
|
||
elif q > 2 and start is not None:
|
||
spans.append((start, i - 1))
|
||
start = None
|
||
if start is not None:
|
||
spans.append((start, total - 1))
|
||
|
||
print()
|
||
print(" ── 塌陷区间(连续采样点合并)──")
|
||
print(" 共 %d 段" % len(spans))
|
||
for a, b in spans[:15]:
|
||
sa = rows[a][0] if rows[a][0] else "第%d点" % a
|
||
sb = rows[b][0] if rows[b][0] else "第%d点" % b
|
||
print(" %-10s -> %-10s 持续 %d 个采样点 (quic 最低 %d)"
|
||
% (sa, sb, b - a + 1, min(quic[a:b + 1])))
|
||
|
||
# 塌陷间隔(周期)
|
||
if len(spans) >= 2:
|
||
gaps = [spans[i + 1][0] - spans[i][0] for i in range(len(spans) - 1)]
|
||
print()
|
||
print(" ── 两次塌陷之间隔多少个采样点 ──")
|
||
print(" %s" % gaps[:15])
|
||
print(" 平均 %.1f 个采样点" % (sum(gaps) / len(gaps)))
|
||
|
||
# 连接数分布
|
||
from collections import Counter
|
||
print()
|
||
print(" ── QUIC 连接数分布 ──")
|
||
for k in sorted(set(quic)):
|
||
c = quic.count(k)
|
||
print(" %2d 条: %4d 次 %5.1f%%" % (k, c, c * 100.0 / total))
|