# -*- coding: utf-8 -*- r'''确认延迟瓶颈到底在哪一段。 对比三段: 1. 局域网直连(设备本机 -> relay 本机) 预期几十毫秒 2. 公网(本机 -> Cloudflare 边缘 -> 隧道 -> 设备) 3. 纯 Cloudflare 边缘 RTT(本机 -> 随便一个 CF 站点) 差值能告诉我们: 2 - 1 = 隧道 + 公网往返的开销 3 = 到边缘的裸 RTT 2 - 3 - 1 = 隧道那一段的开销(设备到边缘) ''' from __future__ import annotations import statistics import sys import time import urllib.request HEADERS = {"User-Agent": "LanRemote/1.4.0"} def timed(url: str, rounds: int = 15) -> list: out = [] for _ in range(rounds): try: start = time.perf_counter() with urllib.request.urlopen( urllib.request.Request(url, headers=HEADERS), timeout=25) as resp: resp.read() if resp.status == 200: out.append((time.perf_counter() - start) * 1000) except Exception: # noqa: BLE001 pass time.sleep(0.3) return out def show(label: str, values: list, rounds: int) -> float: if not values: print(" %-24s 全失败" % label) return float("nan") med = statistics.median(values) print(" %-24s 可用 %2d/%d 中位 %7.0f ms 最快 %7.0f ms" % (label, len(values), rounds, med, min(values))) return med def main() -> int: print(" 分段测延迟(各 15 次取中位数)") print() lan = show("1. 局域网直连", timed("http://192.168.2.156:8080/v1/health"), 15) pub = show("2. 公网(经隧道)", timed("https://relay.xxmxxs.top/v1/health"), 15) edge = show("3. Cloudflare 边缘裸 RTT", timed("https://cloudflare.com/cdn-cgi/trace"), 15) print() print(" 分析:") if lan == lan and pub == pub: print(" 局域网 %.0f ms -> 公网 %.0f ms" % (lan, pub)) print(" 公网比局域网多 %.0f ms" % (pub - lan)) if edge == edge and pub == pub: print() print(" 到 Cloudflare 边缘的裸 RTT: %.0f ms" % edge) print(" 公网请求 %.0f ms,其中边缘往返占 %.0f ms(%.0f%%)" % (pub, edge, edge / pub * 100)) print(" 剩下的 %.0f ms 是:边缘 -> 设备(隧道)那一段 + 服务端处理" % (pub - edge)) print() print(" 结论:") print(" 如果「边缘 -> 设备」那段占比大,说明瓶颈在设备的 4G 上行链路,") print(" Cloudflare 这一侧没得优化了 —— 只能靠换网络或换中转位置。") return 0 if __name__ == "__main__": sys.exit(main())