# -*- coding: utf-8 -*- r'''定位"不稳定"到底在哪一段。 == 已经知道的 == 从本机连 30 次 `https://yk.xxmxxs.top/v1/health`: 成功 25 / 30(**17% 失败**) 失败的那几次都是 TCP 连接阶段就卡住(14~19 秒) 成功的时候中位只要 0.2 秒 **这说明不是服务器慢,是"有时候连不上"。** == 要区分三段 == 我 → Cloudflare边缘 → Cloudflare内部 → 源站(<服务器IP>) → nginx → relay 可能的断点: A. **我 → Cloudflare 边缘**(我这边的网络 / ISP / 到 CF 的线路) B. **Cloudflare 边缘 → 源站**(CF 回源;源站在 AWS 东京/新加坡) C. **源站内部**(nginx / relay) 怎么分: * 直连 `<服务器IP>:443`(绕过 Cloudflare)—— 稳的话说明 C 没问题 * 连 `yk.xxmxxs.top:443`(走 Cloudflare)—— 不稳的话说明 A 或 B 有问题 * 再对比别的走 Cloudflare 的站(比如 cloudflare.com 自己)—— 它也抖的话说明是 **A**(我这边到 CF 的网络) **这一步很关键**:如果是 A,那"网站不稳定"里**有一部分是本地网络的问题**, 不是服务器的问题 —— 用户在学校用可能是完全不同的情况。 ''' from __future__ import annotations import socket import ssl import statistics import sys import time from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT / "_build")) HOSTFILE = ROOT / "_build" / ".lightsail_host" IP = HOSTFILE.read_text(encoding="utf-8").strip() def probe(host, port=443, path="/", use_tls=True, timeout=8, host_hdr=None): """测一次。返回 (结果, TCP耗时, 总耗时, 说明)""" t0 = time.perf_counter() try: s = socket.create_connection((host, port), timeout=timeout) t_tcp = time.perf_counter() - t0 if use_tls: ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE s = ctx.wrap_socket(s, server_hostname=host_hdr or host) hdr = (host_hdr or host).encode() s.send(b"GET " + path.encode() + b" HTTP/1.1\r\nHost: " + hdr + b"\r\nUser-Agent: probe\r\nConnection: close\r\n\r\n") data = s.recv(300) t_all = time.perf_counter() - t0 s.close() code = data.split(b" ")[1].decode() if b" " in data else "?" return ("ok", t_tcp, t_all, code) except Exception as exc: # noqa: BLE001 return (type(exc).__name__, time.perf_counter() - t0, None, str(exc)[:34]) def batch(label, **kw): print(" ── %s ──" % label) n = kw.pop("n", 15) ok = 0 slow = [] fails = [] for i in range(n): kind, tcp, total, note = probe(**kw) if kind == "ok": ok += 1 if tcp > 1.0: slow.append((i + 1, tcp)) else: fails.append((i + 1, kind, tcp, note)) print(" %d/%d 成功 失败 %d" % (ok, n, len(fails))) if slow: print(" 慢的:%s" % ", ".join("#%d=%.1fs" % x for x in slow)) if fails: for i, kind, secs, note in fails[:6]: print(" ✗ #%d %s %.1fs %s" % (i, kind, secs, note)) return ok, len(fails) def main() -> int: print("=" * 62) print(" 定位不稳定在哪一段") print("=" * 62) print() a = batch("A. 直连源站 IP(绕过 Cloudflare)", host=IP, port=443, use_tls=False, path="/v1/health", host_hdr="yk.xxmxxs.top", n=15) print() b = batch("B. 走域名(经 Cloudflare)", host="yk.xxmxxs.top", port=443, path="/v1/health", n=15) print() c = batch("C. 对照:Cloudflare 自己的站", host="cloudflare.com", port=443, path="/", n=15) print() d = batch("D. 对照:另一个大站(百度)", host="www.baidu.com", port=443, path="/", n=15) print() print("=" * 62) print(" 判读") print("=" * 62) print(" A=直连源站 B=经Cloudflare C/D=对照") print(" A:%d失败 B:%d失败 C:%d失败 D:%d失败" % (a[1], b[1], c[1], d[1])) print() if a[1] == 0 and b[1] > 0: print(" → **源站没问题,问题在 Cloudflare 那一段**(或本地到 CF 的线路)") if c[1] > 0 or d[1] > 0: print(" 而且对照组也抖 → 更像是**本地网络到外网**的问题,") print(" 不是我们服务器或 Cloudflare 的锅。") else: print(" 对照组稳定 → 说明是 **Cloudflare ↔ 源站回源**这一段。") elif a[1] > 0: print(" → **直连源站也会失败** —— 那问题可能在源站或本地网络") if d[1] > 0: print(" 但百度也抖 → 先怀疑**本地网络**(换个网络再测)") else: print(" → 这一轮没测出抖动,说明是**间歇性**的(多测几轮)") return 0 if __name__ == "__main__": sys.exit(main())