Files
ykxmz/_build/verify_showcase.sh
xmz7891 1f05084f51 隧道"假活"真因修复 + 中转管理后台重做
用户反馈两件事:
  1. 早上打开 relay.xxmxxs.top 看到 Cloudflare Error 1033 —— "这就是你说的优化好了?"
  2. "中转管理那边 ui 界面大改,现在难看的要死"

============ 一、隧道 1033/502/530 的真因 ============

之前我只测 15~25 次就说"可用率 100%",太草率 ——
实际是**间歇性假活**:隧道显示 ha_connections=2 连着,
公网却 502/530/000。watchdog 日志把过程记了下来。

根因:**4G 链路静默断开 TCP 连接**(不发 FIN/RST,双方都以为还活着)。
Cloudflare 把请求发到这条僵尸连接上就回错误。
Linux 默认 tcp_keepalive_time = **7200 秒(2 小时)**才发现,
中间这段时间服务一直"看着在线、实际打不开"。

修法(都有实测数据支撑):
  1. tcp_keepalive 30 秒 + 每 10 秒探测 3 次
     => 最多约 60 秒发现僵尸连接并重连
  2. 隧道连接数 2 -> 4
     (对照实验:http2+2 只有 1 条连上时公网 0/12;
       http2+4 稳定 12/12。连接数太少会出现"只有 1 条"的危险窗口)
  3. 协议定为 http2(cloudflared 自检说 TCP 7844 被墙,
     但实测 http2 反而比 quic 稳)

实测:http2+4 之后公网 40/40 = 100%,最慢 1.3 秒,0 次重连。

============ 二、中转管理后台重做 ============

原来是几百行内联在 relay.py 的 f-string 里(HTML+CSS+JS 全挤一起),
改一处样式要在一堆转义花括号里翻。拆成独立模块 relay/admin.py。

新版设计(对齐官网那套白色简洁):
  * 吸顶顶栏:品牌 + 运行状态 + 版本/内存/请求数
  * 公网地址给最大权重(这是用户最需要复制的东西)
  * 四个数字卡(在线/会话数带颜色区分)
  * 设备表卡片:状态圆点、等宽配对码、行悬停
  * 工具卡:网络体检 + 下载区并排
  * 空状态改成图标+引导文案,不再是干巴巴一句
  * 窄屏时表格自动变卡片

relay.py 从 2089 行缩到 1550 行。

============ 三、顺手修的两个真 bug ============

1. 设备记录只增不减
   self.devices 从不清理,被控端每次换端口/重装就多一条,
   实测一天攒了 75 条僵尸记录,/v1/health 从几 KB 涨到 20KB。
   加 DEVICE_TTL(6 小时)在 snapshot() 里清。

2. 配对码映射也没清
   RELAY.codes 和 devices 是一对孪生 dict,
   只清 devices 会留下指向已删设备的孤儿条目 ——
   管理页显示"配对码占用 131",实际一台设备都没有。
   现在一起清。

============ 四、我自己造的两次事故(如实记录) ============

1. 删文件删过头
   用"从 _admin_page 截到文件末尾"的方式替换方法,
   但 _admin_page 后面**还有 _esc/_kb/_uptime/class Server/main()**。
   结果 relay 起不来,systemd 重启 24 次,所有接口 000。
   教训:**"删到文件末尾"之前必须先确认末尾有什么。**

2. ADMIN_PATH 引用了不存在的常量
   路由里写的是字面量,我却在新代码里用了 ADMIN_PATH,
   管理页一访问就 NameError。现在统一定义了常量。

二者都是"改完没立刻验"造成的。现在每次改完都跑一遍
管理页 + 官网 + 关键接口的回归。
2026-10-07 09:34:53 +08:00

56 lines
2.4 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 验收:产品展示区块 + 截图路由 + 原有功能没被搞坏
set -u
BASE=http://127.0.0.1:8080
PUB=https://relay.xxmxxs.top
KEY=$(cat /root/lanremote-relay/data/admin_key.txt 2>/dev/null)
curl -s --max-time 15 "$BASE/" -o /tmp/s.html
size=$(wc -c < /tmp/s.html)
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "$BASE/")
echo " 官网 HTTP $code $size 字节"
echo
echo " 新增区块:"
has() { if grep -q "$1" /tmp/s.html; then echo " ✓ $2"; else echo " ✗ $2"; fi; }
has 'id="shots"' '产品展示(长什么样)'
has 'class="watch"' '手表界面 mockup'
has 'w-tab' '手表标签条'
has '/shot/pc-main.png' '电脑端真实截图'
has 'id="how-connect"' '怎么连上的'
has 'class="flow"' '连接方式示意'
has '局域网 3 ms' '局域网延迟标注'
echo
echo " 区块计数:"
printf " 手表标签 %s 个(应为 10)\n" "$(grep -o 'w-tab' /tmp/s.html | wc -l)"
printf " 手表按钮 %s 个(应为 9)\n" "$(grep -o 'class="w-btn"' /tmp/s.html | wc -l)"
printf " 连接示意 %s 列(应为 2)\n" "$(grep -o 'class="flow-col"' /tmp/s.html | wc -l)"
echo
echo " 原有区块还在吗:"
for pair in "吸顶导航:nav-in" "Hero:hero" "功能网格:id=\"features\"" \
"三步上手:id=\"how\"" "下载区:id=\"download\"" "FAQ:id=\"faq\""; do
has "${pair#*:}" "${pair%%:*}"
done
echo
echo " 截图路由:"
echo " /shot/pc-main.png HTTP $(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "$BASE/shot/pc-main.png") $(curl -s -o /dev/null -w '%{size_download}' --max-time 15 "$BASE/shot/pc-main.png") 字节"
echo " 路径穿越 /shot/../relay.py HTTP $(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "$BASE/shot/../relay.py")"
echo " 非图片 /shot/x.txt HTTP $(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "$BASE/shot/x.txt")"
echo
echo " 其它功能:"
echo " /v1/health HTTP $(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "$BASE/v1/health")"
echo " /zhongzhuanzhan HTTP $(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "$BASE/zhongzhuanzhan")"
echo " /v1/downloads HTTP $(curl -s -o /dev/null -w '%{http_code}' --max-time 15 "$BASE/v1/downloads")"
echo " health 大小 $(curl -s --max-time 10 "$BASE/v1/health" | wc -c) 字节"
echo
echo " 公网:"
for i in 1 2 3 4 5; do
printf " %d: HTTP %s\n" "$i" "$(curl -s -o /dev/null -w '%{http_code}' --max-time 20 -H 'User-Agent: LanRemote/1.4.0' "$PUB/")"
done