NetStable
NetStable 是一个独立的 Go Web 测速项目,用于测试“打开网页的用户浏览器”到“部署服务器”的上传、下载和延迟。用户打开网页即可开始测试,页面会实时显示下载速度、上传速度、延迟、稳定评分和历史时序曲线。
功能
- 同一时间只允许一个用户真正进行测速。
- 其他用户发起请求时会进入 FIFO 队列,页面和 CLI 会显示当前排第几位,并在前面的用户完成后自动开始。
- 启动时可设置程序理论最高带宽,例如
-bandwidth-limit-mbps 30将测试流量限制到 30 Mbps。 - 页面展示当前设置的理论最高限值。
- 一次测试按阶段执行:先连续下载指定时长,再连续上传同样时长。页面固定提供
15s和30s两档,默认30s。 - 手动停止、刷新页面或 CLI 中断时会取消当前会话并释放队列,后续用户会自动前移。
- 下载/上传峰值使用连续样本的持续吞吐口径,避免单个短请求计时误差造成虚高峰值。
- 保存每次测试的完整样本曲线、摘要、脱敏后的用户 IP、地区和运营商信息;ISP 缺失时显示“未知运营商”。
- 所有历史测试用户数据通过网页和
/api/records提供。 - 历史时序图展示不同时段的平均下载速度变化。
- 页面通过 SSE 心跳维持一条辅助长连接,用于显示连接状态和服务配置。
- CLI 支持 HTTP 模式和
iperf3模式;iperf3模式由服务端在线随机生成一次性高端口,并复用同一个全局测速锁。 - 页面可复制一键下载测试命令:用户服务器会从当前网站下载 CLI 二进制,然后立即发起测试。
- 内置 GitHub 开源
ip2region_v4.xdbIPv4 数据库,优先离线解析地区和 ISP,避免外部 API 限流。 - 静态页面嵌入二进制,部署时只需要上传一个可执行文件。
本地运行
go test ./...
go run ./cmd/netstable -listen 127.0.0.1:18080 -data data/records.jsonl
打开 http://127.0.0.1:18080/。
构建
make test
make build
生成文件位于 dist/netstable。
更新内置 IP 数据库:
make update-ip-db
Release 二进制
线上可以通过 Gitea Release 发布可直接下载的二进制压缩包,不建议把二进制提交到 Git 仓库。
仓库设置为 public 后,用户不需要登录即可下载 Release 附件。把下面命令中的 https://gitea.example.com/owner/netstable 替换成实际 public 仓库地址即可一键下载并启动:
VERSION=v0.1.0 REPO=https://gitea.example.com/owner/netstable sh -c 'set -e; arch=$(uname -m); case "$arch" in x86_64) arch=amd64;; aarch64|arm64) arch=arm64;; *) echo "unsupported arch: $arch"; exit 1;; esac; tmp=$(mktemp -d); curl -fsSL "$REPO/releases/download/$VERSION/netstable-$VERSION-linux-$arch.tar.gz" | tar -xz -C "$tmp"; sudo install -m 0755 "$tmp/netstable" /usr/local/bin/netstable; sudo mkdir -p /var/lib/netstable; sudo /usr/local/bin/netstable -listen 0.0.0.0:18080 -data /var/lib/netstable/records.jsonl'
生成 Linux release 附件:
make release VERSION=v0.1.0
生成内容:
dist/netstable-v0.1.0-linux-amd64.tar.gzdist/netstable-v0.1.0-linux-arm64.tar.gzdist/checksums.txt
在 Gitea 的仓库页面创建 Release,标签填 v0.1.0,然后上传上述附件。用户可以直接下载后运行:
tar -xzf netstable-v0.1.0-linux-amd64.tar.gz
chmod +x netstable
./netstable -listen 0.0.0.0:18080 -data /var/lib/netstable/records.jsonl -downloads-dir /var/lib/netstable/downloads
Linux 部署
scp dist/netstable root@SERVER:/usr/local/bin/netstable
ssh root@SERVER 'mkdir -p /var/lib/netstable && chmod +x /usr/local/bin/netstable'
可直接启动:
/usr/local/bin/netstable -listen 0.0.0.0:18080 -data /var/lib/netstable/records.jsonl -downloads-dir /var/lib/netstable/downloads
也可以使用 deploy/netstable.service:
scp deploy/netstable.service root@SERVER:/etc/systemd/system/netstable.service
ssh root@SERVER 'systemctl daemon-reload && systemctl enable --now netstable'
CLI 测试
同一个二进制也可以作为客户端,在其他服务器上直接测试到部署节点的上传、下载和延迟。CLI 会复用 Web API,所以仍然遵守“同一时间只允许一个用户测速”的锁;如果前面有人正在测,CLI 会显示当前排队位置并持续等待,轮到自己后自动开始。
HTTP 模式不依赖外部程序:
./netstable client -server http://103.46.93.38:18080 -duration 30
网页复制的一键命令会先下载 CLI 再测试,适合用户服务器没有 netstable 的情况:
arch=$(uname -m); case "$arch" in x86_64) arch=amd64;; aarch64|arm64) arch=arm64;; *) echo "unsupported arch: $arch"; exit 1;; esac; tmp=$(mktemp -d); curl -fsSL 'http://103.46.93.38:18080/downloads/netstable-linux-'"$arch"'.tar.gz' | tar -xz -C "$tmp" && chmod +x "$tmp/netstable" && "$tmp/netstable" client -server 'http://103.46.93.38:18080' -duration 30
iperf3 模式需要客户端和服务端都安装 iperf3。CLI 会先请求服务端创建一次性会话,服务端随机开放一个临时高端口,测试结束后回写记录并释放锁:
./netstable client -mode iperf3 -server http://103.46.93.38:18080 -duration 30 -protocol tcp
UDP 示例:
./netstable client -mode iperf3 -server http://103.46.93.38:18080 -duration 30 -protocol udp -bandwidth-mbps 30
反向下载测试,即服务端发送到 CLI 客户端:
./netstable client -mode iperf3 -server http://103.46.93.38:18080 -duration 30 -reverse
输出 JSON:
./netstable client -server http://103.46.93.38:18080 -duration 30 -json
常用参数:
-server: NetStable 服务端地址。-mode:http或iperf3,默认http。-duration: 每阶段时长,先下载同样秒数,再上传同样秒数。-timeout: HTTP 请求超时,单位毫秒;iperf3模式中也作为测试时长之外的额外等待时间,默认3000。-target: 保存到记录里的目标标签,默认使用-server的 host。-download-bytes: 每次下载请求大小,默认 4 MiB。-upload-bytes: 每次上传请求大小,默认 2 MiB。-protocol:iperf3模式使用tcp或udp,默认tcp。-reverse:iperf3反向模式,服务端向 CLI 客户端发送流量。-bandwidth-mbps:iperf3目标带宽,默认跟随服务端-bandwidth-limit-mbps。-iperf3-path:iperf3可执行文件路径,默认iperf3。-quiet: 不输出每个样本,只输出最终摘要。
参数
-listen: HTTP 监听地址,默认:8080;部署示例使用高端口18080。-data: JSONL 记录文件,默认data/records.jsonl。-static: 可选静态资源目录;为空时使用嵌入资源。-downloads-dir: 可选二进制下载目录。目录中可放netstable-linux-amd64.tar.gz和netstable-linux-arm64.tar.gz,通过/downloads/提供给网页一键命令下载。-geo-base: 在线 IP 归属地 API fallback 地址,默认https://ipapi.co,并在默认源限流时自动尝试https://ipinfo.io;内置ip2region会优先查询,设为空可关闭在线 fallback。-geo-timeout: IP 归属地查询超时,默认2s。-trust-proxy-headers: 是否信任CF-Connecting-IP、X-Real-IP、X-Forwarded-For。直连公网时不要开启;放在可信反向代理后面时开启。-bandwidth-limit-mbps: 程序理论最高带宽限制,单位 Mbps。示例:服务器 50 Mbps,希望测速程序最多使用 30 Mbps,则设置为30;默认0表示不限速。-iperf3-path: 服务端启动一次性iperf3会话时使用的可执行文件路径,默认iperf3。
Gitea
仓库可以直接推送到 Gitea。设置 remote 后执行:
git remote add origin <gitea-repo-url>
git push -u origin codex/go-network-stability-tester