#!/bin/bash # 严谨对照 v2:http2+4 vs quic+6,用**真实的长轮询模式**测。 # # v1 的问题: # * 只跑 5 分钟、每 3 秒一个新连接 —— 那是"冷启动"模式, # 而真实业务是**长轮询复用同一条连接**,两者差别很大。 # * 判定规则太粗(98% vs 100% 就回滚), # 忽略了 P90 从 16.8 秒改善到 2.8 秒这个数量级的差异。 # # v2 的做法: # * 用 curl 一次给多个 URL —— 复用同一条连接,贴近长轮询 # * 每轮 10 分钟 # * 记录 成功率 / 中位 / P90 / P99 / 最大 / 失败时刻 # * 用真实的长轮询接口 /v1/agent/poll(挂 60 秒), # 量"一次完整长轮询"的耗时分布 —— 这才是用户真正经历的 set -u UA='LanRemote/1.8.0' PUB=https://relay.xxmxxs.top SVC=/etc/systemd/system/lanremote-tunnel.service BACKUP=/root/lanremote-tunnel.service.bak.v2.$(date +%s) cp -a "$SVC" "$BACKUP" set_params() { local proto="$1" conns="$2" 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 systemctl daemon-reload systemctl restart lanremote-tunnel } wait_ready() { local want="$1" for i in $(seq 1 30); 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}') [ "${n:-0}" -ge "$want" ] && return 0 done return 1 } # ---- 用真实长轮询接口测 ---- # 注册一台探针设备,poll 会挂 60 秒再返回(没有数据时) probe_device() { DEV="probev2-$(date +%s)" REG=$(curl -s --max-time 30 -X POST "$PUB/v1/agent/register" \ -H 'Content-Type: application/json' -H "User-Agent: $UA" \ -d "{\"deviceId\":\"$DEV\",\"code\":\"777777\",\"name\":\"probev2\",\"version\":\"1.8.0\"}") echo "$REG" | python3 -c "import sys,json; print(json.load(sys.stdin).get('token',''))" 2>/dev/null echo "$DEV" > /tmp/probe_dev.txt } measure_poll() { local label="$1" token="$2" rounds="${3:-8}" local ok=0 fail=0 times=() fails="" echo " ── $label:$rounds 次真实长轮询(每次挂 60 秒)──" for i in $(seq 1 "$rounds"); do out=$(curl -s -o /dev/null -w '%{http_code} %{time_total}' --max-time 100 \ -X POST "$PUB/v1/agent/poll" -H "X-Token: $token" -H "User-Agent: $UA") code=$(echo "$out" | awk '{print $1}') secs=$(echo "$out" | awk '{printf "%.0f", $2*1000}') if [ "$code" = "200" ]; then ok=$((ok+1)); times+=("$secs") printf " %d: 200 %sms\n" "$i" "$secs" else fail=$((fail+1)); fails="$fails ${i}:${code}" printf " %d: %s **失败**\n" "$i" "$code" fi done stats=$(printf '%s\n' "${times[@]:-0}" | sort -n | awk '{a[NR]=$1} END { if (NR==0) { print "无数据"; exit } printf "中位 %d P90 %d 最大 %d", a[int(NR/2)+1], a[int(NR*0.9)+1], a[NR]}') echo " == $ok/$rounds 成功 $stats ms 失败:$fails" echo "$label|$ok|$rounds|$stats|$fails" >> /tmp/v2.txt echo } rm -f /tmp/v2.txt echo "════════ 基线:http2 + 4 ════════" set_params http2 4 wait_ready 4 && echo " 连接就绪" || echo " ! 没建齐" sleep 15 TOKEN=$(probe_device) echo " 探针 token ${#TOKEN} 字符" measure_poll "http2+4" "$TOKEN" 8 echo "════════ 候选:quic + 6 ════════" set_params quic 6 wait_ready 6 && echo " 连接就绪" || echo " ! 没建齐" sleep 15 TOKEN=$(probe_device) echo " 探针 token ${#TOKEN} 字符" measure_poll "quic+6" "$TOKEN" 8 echo "════════ 汇总(每次长轮询的耗时,理想值 ≈ 61000ms)════════" printf " %-10s %-10s %s\n" "配置" "成功" "耗时" while IFS='|' read -r label ok total stats fails; do printf " %-10s %-10s %s\n" "$label" "$ok/$total" "$stats" done < /tmp/v2.txt echo echo "════════ 决策:主要看尾部延迟(用户体感就是这个)════════" B=$(grep '^http2+4' /tmp/v2.txt | cut -d'|' -f4) Q=$(grep '^quic+6' /tmp/v2.txt | cut -d'|' -f4) echo " 基线 $B" echo " 候选 $Q" # 取 P90 数字比较 BP=$(echo "$B" | grep -oE 'P90 [0-9]+' | grep -oE '[0-9]+') QP=$(echo "$Q" | grep -oE 'P90 [0-9]+' | grep -oE '[0-9]+') echo if [ -n "${BP:-}" ] && [ -n "${QP:-}" ]; then if [ "$QP" -lt "$BP" ]; then echo " → quic+6 的 P90(${QP}ms)优于基线(${BP}ms),采用 quic+6" # 已经设成 quic 6 了,不用动 else echo " → quic+6 的 P90(${QP}ms)不如基线(${BP}ms),回滚" cp -a "$BACKUP" "$SVC" systemctl daemon-reload systemctl restart lanremote-tunnel fi else echo " → 数据不足,保守回滚" cp -a "$BACKUP" "$SVC" systemctl daemon-reload systemctl restart lanremote-tunnel fi sleep 15 echo echo " 最终参数: $(grep -oE '\-\-protocol [a-z0-9]+|--ha-connections [0-9]+' "$SVC" | tr '\n' ' ')" echo " 连接数: $(curl -s --max-time 5 http://127.0.0.1:20241/metrics 2>/dev/null | grep '^cloudflared_tunnel_ha_connections' | awk '{print $2}')" # 清探针 KEY=$(cat /root/lanremote-relay/data/admin_key.txt 2>/dev/null) DEV=$(cat /tmp/probe_dev.txt 2>/dev/null) [ -n "${DEV:-}" ] && curl -s --max-time 20 -X POST "http://127.0.0.1:8080/v1/admin/delete" \ -H "X-Admin: $KEY" -H 'Content-Type: application/json' \ -d "{\"deviceId\":\"$DEV\"}" > /dev/null 2>&1 echo " 备份: $BACKUP"