Files

5.5 KiB
Raw Permalink Blame History

SpeedTest · 网速测试服务

基于 Go + Gin + SQLite (GORM) 的网页网速测试服务,支持 延迟、下载、上传 三项测试, 测速结果自动入库并生成 排行榜(下载榜 / 上传榜 / 延迟榜)。

功能特性

  • 延迟测试: 前端连续 10 次 ping,取中位数作为延迟、平均绝对偏差作为抖动
  • ⬇️ 下载测试: 固定测速 10 秒——负载根据实测速率自适应(每轮约 2 秒), 快速连接自动加大负载填满 10 秒,慢速连接用小负载同样 10 秒内完成
  • ⬆️ 上传测试: 同样的固定 10 秒自适应策略
  • 🏆 排行榜: 单表同时展示延迟 / 下载 / 上传,点击列头动态排序(再点切换升降序, 延迟默认升序、速度/时间默认降序);用户列显示地区 + 浏览器(离线 ip2region 解析地区、 UA 解析浏览器系统),不展示任何 IP;测速完成后自动高亮"我的成绩"(含真实名次, localStorage 持久化,刷新页面仍高亮)
  • 🌐 IP 处理: 客户端 IP 仅后台保存(数据库),用于地区解析与调试,不在排行榜展示; 页面上方徽标显示"你的公网 IP · 地区";服务器直接识别 IP(Caddy X-Real-IP), 无外部 IP 查询依赖
  • 📍 地区解析: 内置 ip2region v4 离线库(data/ip2region_v4.xdb,11MB),纯本地解析 零外部依赖,加载失败时地区优雅降级为"未知地区"
  • 🔒 Unix socket 监听: 由 Caddy 反代对外提供 HTTPS,不暴露 TCP 端口

项目结构

speedtest/
├── main.go                     # 入口:加载配置 → 初始化数据库 → 启动 Web
├── install.sh                  # 一键安装/更新/卸载/管理脚本(systemd
├── config/
│   ├── config.go               # TOML 配置加载(缺失自动生成/补全)
│   └── defaults.go             # 默认路径与默认值
├── internal/
│   ├── db/
│   │   ├── db.go               # GORM 初始化 + 自动迁移
│   │   └── models.go           # SpeedTestResult 数据模型
│   ├── store/
│   │   ├── stores.go           # 数据访问层聚合
│   │   └── result_store.go     # 测速结果增查(Top N / Count
│   └── web/
│       ├── server.go           # Gin 引擎 + 路由 + Unix socket/TCP 监听
│       ├── handlers/
│       │   └── speedtest.go    # ping/download/upload/result/rankings
│       └── templates/
│           └── index.html      # 前端单页(原生 JS,无外部依赖)

本地开发

# 编译(SQLite 依赖 CGO
CGO_ENABLED=1 go build -ldflags="-s -w" -o speedtest .

# 本地运行(可用 SPEEDTEST_CONFIG 覆盖配置路径,见 test.toml 示例)
SPEEDTEST_CONFIG=./test.toml ./speedtest

部署(生产)

sudo ./install.sh install

脚本会自动完成:创建 speedtest 系统用户 → 创建目录 → 从 Gitea 拉取代码 → 编译(CGO_ENABLED=1)→ 部署二进制与模板 → 生成 systemd 服务 → 启动并设置开机自启。

项目 路径
程序目录 /opt/speedtest
Unix socket /opt/speedtest/web.sock
配置文件 /etc/speedtest/speedtest.toml
SQLite 数据库 /srv/speedtest/speedtest.db
日志 journalctl -u speedtest -f

Caddy 反代配置

speedtest.lmve.net {
	reverse_proxy unix//opt/speedtest/web.sock {
		header_up X-Real-IP {remote_host}
		header_up Host {host}
	}
}

配置文件

程序首次启动自动生成 /etc/speedtest/speedtest.toml(缺失项自动补全):

[database]
  driver = "sqlite"
  dsn = "/srv/speedtest/speedtest.db"

[web]
  addr = "/opt/speedtest/web.sock"   # 以 / 开头为 unix socket,否则为 TCP 端口

[speedtest]
  max_download_bytes = 536870912     # 单次下载请求上限(默认 512 MB)
  max_upload_bytes = 536870912       # 单次上传请求上限(默认 512 MB)

注:默认上限 512MB 服务于前端自适应测速(快速连接负载会翻倍增长); 旧版本配置中的 100MB 上限可手动调大,或删除配置行后重启让程序补全默认值。

API

方法 路径 说明
GET / 测速页面
GET /api/ping 延迟探测(返回 {"pong":true,"ts":...,"client_ip":...,"location":...}
GET /api/download?size=N 下载测速,流式返回 N 字节随机数据(默认 10MB,上限 512MB)
POST /api/upload 上传测速,接收请求体并返回 received/elapsed_s/mbps
POST /api/result 提交结果 {latency_ms, jitter_ms, download_mbps, upload_mbps}IP/UA 由服务器识别)
GET /api/rankings?sort=&order=&include_id= 排行榜单表:sort ∈ download/upload/latency/createdorder ∈ asc/descinclude_id 附加指定记录(真实名次 + is_mine);条目含 location/browser不含 IP

客户端 IP 由服务器直接识别(Caddy 注入的 X-Real-IP),前端不调用任何外部 IP 服务; client_ip / server_ip 字段为 API 兼容保留(可选)。公网 IP 打码保护隐私; NAT 场景下的内网来源 IP 在排行榜中完整标注,供站长调试区分设备。