Files
xmz7891 b1119d0da6 修「局域网连接被中转劫持」+ 长轮询 15s→60s
用户报两个问题:
  1. 局域网能搜到电脑,IP/端口/配对码都对,点连接**没有任何反应**
  2. 走中转 1426ms 延时,一会儿就 502

========== 一、局域网被劫持(真 bug)==========

MainActivity.connect() 里:

    boolean usedLan = !relayUrl().isEmpty() ? false : true;
    if (!relay.isEmpty()) {
        reply = client.connectViaRelay(...);      // 走中转
    } else {
        reply = client.connect(host, port, ...);  // 才走局域网
    }

**只看「中转设置里填没填地址」,填了就一律走中转,
完全无视用户填的局域网 IP 和端口。**

而中转单次超时是 40 秒 —— 用户点完就卡在「正在连接…」
四十秒,在他看来就是"没有任何反应"。

影响两条路:
  * 「局域网连接」页面填 IP 直连(connectLanTyped)
  * 首页「已配对的电脑」点一下重连(quickConnect)

修法:给 connect() 加 preferLan 参数。明确要走局域网时
**先直连(6 秒超时,局域网本该是毫秒级),失败再退回中转**,
保证最终能连上。

顺带两个体验改进:
  * 设备列表里,保存的 IP 和手表不同网段时标「⚠ 地址可能已过期」
    (用户截图里那个 192.168.2.64 就是过期地址,电脑早换成
      192.168.10.103 了)
  * quickConnect 判断出地址过期就跳过直连,直接走中转查最新地址 ——
    省掉那 6 秒白等

========== 二、长轮询 15 秒 -> 60 秒 ==========

实测隧道每次请求要多花 1~2 秒(CF 边缘路由 + 回源):

    本机直连 60 秒的 poll  ->  60.0s
    走公网同一个 poll      ->  61.5~62.0s

这个开销是**按次数**收的:
    15 秒一循环 -> 一天 5760 次/端,光路费 2.4~3.2 小时
    60 秒一循环 -> 一天 1440 次/端,光费 0.6~0.8 小时
而且请求越频繁,撞上丢包/重连窗口的概率越大。

**不会让命令变慢**:长轮询是"有数据立刻返回"(device.event 唤醒),
拉长只是减少空转重开。实测 60 秒长轮询穿隧道 4/4 通过;
Cloudflare 单请求上限 100 秒,留了 40 秒余量。

三层同步改(客户端超时必须显著大于服务端 hold):
  * relay/relay.py                    RELAY_POLL 默认 25 -> 60
  * windows/lanremote/relay.py        POLL_TIMEOUT 40 -> 90
  * android .../RelayTransport.java   POLL_TIMEOUT_MS 40000 -> 90000

========== 三、A/B 实测(还在跑更严谨的一轮)==========

短测发现基线 http2+4 虽然 100% 成功,但 **P90 是 16.8 秒**
(每 10 次有 1 次卡十几秒 —— 正是用户说的"没反应"),
而 quic+6 的 P90 只有 2.8 秒。正在用真实长轮询模式
跑 10 分钟对照确认。
2026-10-07 14:11:33 +08:00

108 lines
3.8 KiB
Bash

#!/bin/bash
# 受控 A/B:隧道协议和连接数,哪个在"稳 + 快"上更好。
#
# 背景:
# 实测隧道大多稳(12/12),但每个请求稳定吃 ~1100ms 回源延迟。
# 而且日志里 i/o timeout 不少(最近 800 行 104 次),
# 说明有些 edge IP 连得很差(实测最慢那个 1331ms,最快的 146ms)。
#
# 假定:连接数多一些,撞上"慢 IP"的窗口就小一些。
# QUIC 在多丢包下恢复更好(没有跨流的队头阻塞),但之前测
# "http2 比 quic 稳" —— 那是连接建立阶段的观感,这次量真实请求。
#
# 组合:
# http2 + 4 (当前配置,基线)
# http2 + 6
# quic + 4
# quic + 6
#
# 每个组合:重启隧道 -> 等连接建齐 -> 打 20 次 -> 记录
# 成功率 / 中位耗时 / P90 / 连接数
set -u
URL=https://relay.xxmxxs.top/v1/health
UA='LanRemote/1.8.0'
SVC=/etc/systemd/system/lanremote-tunnel.service
BACKUP=/root/lanremote-tunnel.service.bak.$(date +%s)
cp -a "$SVC" "$BACKUP"
echo " 备份: $BACKUP"
echo " 原参数:"
grep -A3 'ExecStart' "$SVC" | grep -E 'protocol|ha-connections|edge-ip' | sed 's/^/ /'
echo
run_combo() {
local proto="$1" conns="$2" label="$3"
echo "════════ $label ════════"
# 改参数
if grep -q '\-\-protocol' "$SVC"; then
sed -i "s/--protocol [a-z0-9]*/--protocol $proto/" "$SVC"
else
sed -i "s|\(ExecStart=.*cloudflared tunnel\)|\1 --protocol $proto|" "$SVC"
fi
if grep -q '\-\-ha-connections' "$SVC"; then
sed -i "s/--ha-connections [0-9]*/--ha-connections $conns/" "$SVC"
else
sed -i "s|\(ExecStart=.*cloudflared tunnel\)|\1 --ha-connections $conns|" "$SVC"
fi
grep -oE '\-\-protocol [a-z0-9]+|--ha-connections [0-9]+' "$SVC" | tr '\n' ' ' | sed 's/^/ 参数: /'
echo
systemctl daemon-reload
systemctl restart lanremote-tunnel
# 等连接建齐
built=0
for i in $(seq 1 24); do
sleep 5
n=$(curl -s --max-time 4 http://127.0.0.1:20241/metrics 2>/dev/null \
| grep '^cloudflared_tunnel_ha_connections' | awk '{print $2}')
if [ "${n:-0}" -ge "$conns" ]; then built="$n"; break; fi
done
echo " 连接建齐: ${built:-0}/$conns(等了 ${i}0 秒)"
# 预热几次,跳过建连阶段的冷启动
for i in 1 2 3; do curl -s -o /dev/null --max-time 20 -H "User-Agent: $UA" "$URL"; sleep 1; done
# 正式测
ok=0; times=()
for i in $(seq 1 20); do
out=$(curl -s -o /dev/null -w '%{http_code} %{time_total}' --max-time 30 -H "User-Agent: $UA" "$URL")
code=$(echo "$out" | awk '{print $1}')
ms=$(echo "$out" | awk '{printf "%d", $2*1000}')
times+=("$ms")
[ "$code" = "200" ] && ok=$((ok+1))
sleep 1
done
stats=$(printf '%s\n' "${times[@]}" | sort -n | awk '{a[NR]=$1} END {
p90 = a[int(NR*0.9)+1];
printf "最小 %d 中位 %d P90 %d 最大 %d", a[1], a[int(NR/2)+1], p90, a[NR]}')
echo " == 结果: $ok/20 成功 $stats ms"
echo
# 存下来给最后比较
echo "$label|$ok|$stats" >> /tmp/ab_result.txt
}
rm -f /tmp/ab_result.txt
run_combo http2 4 "A. http2 + 4(基线,当前配置)"
run_combo http2 6 "B. http2 + 6"
run_combo quic 4 "C. quic + 4"
run_combo quic 6 "D. quic + 6"
echo "════════ 汇总 ════════"
cat /tmp/ab_result.txt | sed 's/^/ /'
echo
echo "════════ 回滚到基线(http2 + 4),等后面按结果再定 ════════"
cp -a "$BACKUP" "$SVC"
systemctl daemon-reload
systemctl restart lanremote-tunnel
sleep 20
echo " 已回滚。当前参数:"
grep -oE '\-\-protocol [a-z0-9]+|--ha-connections [0-9]+' "$SVC" | sed 's/^/ /'
echo " 连接数: $(curl -s --max-time 5 http://127.0.0.1:20241/metrics 2>/dev/null | grep '^cloudflared_tunnel_ha_connections' | awk '{print $2}')"