mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 13:40:45 +00:00
149 lines
6.3 KiB
Bash
149 lines
6.3 KiB
Bash
#!/bin/bash
|
||
# 长窗口配比对照用的测量脚本(支持 A/B 两组,各跑 >=40 分钟)
|
||
#
|
||
# 与 rp_long2h.sh 的区别:
|
||
# * 时长可指定(分钟)
|
||
# * **额外采样内存和 CPU**(Lead 问 h2 提到 4 条对 460MB 设备有无影响)
|
||
# * 输出文件名带标签,方便 A/B 分开比对
|
||
#
|
||
# 用法: bash rp_ab_long.sh <标签> <分钟数>
|
||
set -u
|
||
|
||
LABEL=${1:-A}
|
||
MINS=${2:-45}
|
||
BASE=https://relay.xxmxxs.top
|
||
UA='LanRemote/1.8.2'
|
||
DUR=$((MINS * 60))
|
||
HEALTH_EVERY=15
|
||
CONN_EVERY=60
|
||
RES_EVERY=60
|
||
|
||
H=/root/ab_${LABEL}_health.tsv
|
||
C=/root/ab_${LABEL}_conns.tsv
|
||
R=/root/ab_${LABEL}_res.tsv
|
||
S=/root/ab_${LABEL}_summary.txt
|
||
|
||
rm -f "$H" "$C" "$R" "$S"
|
||
|
||
conns_of() {
|
||
curl -s --max-time 4 "http://127.0.0.1:$1/metrics" 2>/dev/null \
|
||
| grep '^cloudflared_tunnel_ha_connections' | awk '{print $2}'
|
||
}
|
||
|
||
M0=$(wc -l < /root/lanremote-relay/tunnel.log 2>/dev/null || echo 0)
|
||
H0=$(wc -l < /root/lanremote-relay/tunnel-h2.log 2>/dev/null || echo 0)
|
||
|
||
T0=$(date +%s)
|
||
NEXT_CONN=$T0
|
||
NEXT_RES=$T0
|
||
|
||
echo " 开始 $LABEL: $(date '+%H:%M:%S') 持续 ${MINS} 分钟"
|
||
|
||
while true; do
|
||
NOW=$(date +%s)
|
||
[ $((NOW - T0)) -ge "$DUR" ] && break
|
||
|
||
out=$(curl -s -o /dev/null -w '%{http_code} %{time_total}' --max-time 25 \
|
||
-H "User-Agent: $UA" "$BASE/v1/health")
|
||
code=$(echo "$out" | awk '{print $1}')
|
||
ms=$(echo "$out" | awk '{printf "%d", $2*1000}')
|
||
echo "$(date '+%Y-%m-%d %H:%M:%S') $code $ms" >> "$H"
|
||
|
||
if [ "$NOW" -ge "$NEXT_CONN" ]; then
|
||
a=$(conns_of 20241); b=$(conns_of 20242)
|
||
echo "$(date '+%Y-%m-%d %H:%M:%S') ${a:-X} ${b:-X}" >> "$C"
|
||
NEXT_CONN=$((NOW + CONN_EVERY))
|
||
fi
|
||
|
||
if [ "$NOW" -ge "$NEXT_RES" ]; then
|
||
# 两个 cloudflared 各占多少常驻内存 + CPU
|
||
qm=0; hm=0; qc=0; hc=0
|
||
for p in $(pgrep cloudflared); do
|
||
proto=$(tr '\0' ' ' < /proc/$p/cmdline 2>/dev/null | grep -oE '\-\-protocol [a-z0-9]+' | awk '{print $2}')
|
||
rss=$(awk '/VmRSS/{print $2}' /proc/$p/status 2>/dev/null)
|
||
cpu=$(ps -o %cpu= -p $p 2>/dev/null | tr -d ' ')
|
||
if [ "$proto" = "quic" ]; then qm=${rss:-0}; qc=${cpu:-0};
|
||
elif [ "$proto" = "http2" ]; then hm=${rss:-0}; hc=${cpu:-0}; fi
|
||
done
|
||
total=$(free -m | awk '/Mem:/{print $3}')
|
||
avail=$(free -m | awk '/Mem:/{print $7}')
|
||
load=$(awk '{print $1}' /proc/loadavg)
|
||
echo "$(date '+%Y-%m-%d %H:%M:%S') ${qm} ${hm} ${qc} ${hc} ${total} ${avail} ${load}" >> "$R"
|
||
NEXT_RES=$((NOW + RES_EVERY))
|
||
fi
|
||
|
||
sleep "$HEALTH_EVERY"
|
||
done
|
||
|
||
M1=$(wc -l < /root/lanremote-relay/tunnel.log 2>/dev/null || echo 0)
|
||
H1=$(wc -l < /root/lanremote-relay/tunnel-h2.log 2>/dev/null || echo 0)
|
||
|
||
{
|
||
echo "════════════════════════════════════════════════════════"
|
||
echo " $LABEL 组 · ${MINS} 分钟 · $(date '+%Y-%m-%d %H:%M:%S')"
|
||
echo "════════════════════════════════════════════════════════"
|
||
echo
|
||
echo "── 配置 ──"
|
||
for svc in lanremote-tunnel lanremote-tunnel-h2; do
|
||
echo " $svc: $(systemctl cat $svc 2>/dev/null | grep -oE '\-\-protocol [a-z0-9]+|\-\-ha-connections [0-9]+' | tr '\n' ' ')"
|
||
done
|
||
echo
|
||
echo "── 公网可用率 ──"
|
||
n=$(grep -c . "$H" 2>/dev/null || echo 0)
|
||
ok=$(awk -F'\t' '$2=="200"' "$H" 2>/dev/null | wc -l)
|
||
echo " $ok/$n = $(awk -v a="$ok" -v b="$n" 'BEGIN{if(b>0)printf "%.2f", a*100/b; else print 0}')%"
|
||
echo " 状态码: $(awk -F'\t' '{print $2}' "$H" 2>/dev/null | sort | uniq -c | tr '\n' ' ')"
|
||
awk -F'\t' '$2=="200"{print $3}' "$H" 2>/dev/null | sort -n | awk '
|
||
{a[NR]=$1}
|
||
END{if(NR==0){print " 无数据"; exit}
|
||
printf " 耗时: 最小 %d 中位 %d P90 %d P99 %d 最大 %d ms\n",
|
||
a[1], a[int(NR/2)+1], a[int(NR*0.9)+1], a[int(NR*0.99)+1], a[NR]}'
|
||
echo " 失败时刻:"
|
||
awk -F'\t' '$2!="200"{print " " $1 " 码=" $2 " " $3 "ms"}' "$H" 2>/dev/null
|
||
echo
|
||
echo "── 连接数 ──"
|
||
awk -F'\t' 'NR>1 && $2 ~ /^[0-9]+$/ && $3 ~ /^[0-9]+$/ {
|
||
t=$2+$3; cnt[t]++
|
||
if (t<=3) low++
|
||
if (t<min || min=="") min=t
|
||
if (t>max) max=t
|
||
} END {
|
||
printf " 最小 %d 最大 %d 平均 %.2f\n", min, max, 0
|
||
printf " 总连接数<=3 的采样: %d 次(占 %.1f%%)\n", low+0, (low+0)*100/NR
|
||
}' "$C" 2>/dev/null
|
||
echo " 分布: $(awk -F'\t' 'NR>1 && $2 ~ /^[0-9]+$/ && $3 ~ /^[0-9]+$/ {print $2+$3}' "$C" | sort -n | uniq -c | tr '\n' ' ')"
|
||
echo
|
||
echo "── 内存 / CPU ──"
|
||
awk -F'\t' 'NR>1 {
|
||
if ($2+0>qm) qm=$2
|
||
if ($3+0>hm) hm=$3
|
||
if ($4+0>qc) qc=$4
|
||
if ($5+0>hc) hc=$5
|
||
if ($6+0>tm) tm=$6
|
||
if (minav=="" || $7+0<minav) minav=$7
|
||
if ($8+0>ld) ld=$8
|
||
} END {
|
||
printf " QUIC 实例常驻内存峰值: %.1f MB\n", qm/1024
|
||
printf " HTTP/2 实例常驻内存峰值: %.1f MB\n", hm/1024
|
||
printf " 两者合计: %.1f MB\n", (qm+hm)/1024
|
||
printf " CPU 峰值: quic %.1f%% http2 %.1f%%\n", qc, hc
|
||
printf " 设备已用内存峰值: %d MB 最少可用: %d MB\n", tm, minav
|
||
printf " 负载峰值: %.2f\n", ld
|
||
}' "$R" 2>/dev/null
|
||
echo
|
||
echo "── 隧道事件(本轮增量)──"
|
||
printf " QUIC 注册 %s 失败 %s 掉线 %s\n" \
|
||
"$(tail -n +$((M0+1)) /root/lanremote-relay/tunnel.log 2>/dev/null | grep -c 'Registered tunnel connection')" \
|
||
"$(tail -n +$((M0+1)) /root/lanremote-relay/tunnel.log 2>/dev/null | grep -c 'Failed to dial')" \
|
||
"$(tail -n +$((M0+1)) /root/lanremote-relay/tunnel.log 2>/dev/null | grep -c 'Lost connection')"
|
||
printf " HTTP/2 注册 %s 失败 %s 掉线 %s\n" \
|
||
"$(tail -n +$((H0+1)) /root/lanremote-relay/tunnel-h2.log 2>/dev/null | grep -c 'Registered tunnel connection')" \
|
||
"$(tail -n +$((H0+1)) /root/lanremote-relay/tunnel-h2.log 2>/dev/null | grep -c 'Failed to dial')" \
|
||
"$(tail -n +$((H0+1)) /root/lanremote-relay/tunnel-h2.log 2>/dev/null | grep -c 'Lost connection')"
|
||
echo
|
||
echo "── watchdog 处置(本轮)──"
|
||
tail -12 /root/lanremote-relay/watchdog.log 2>/dev/null | sed 's/^/ /'
|
||
} > "$S" 2>&1
|
||
|
||
cat "$S"
|