Files
speedtest/README.md
T

119 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SpeedTest · 网速测试服务
基于 **Go + Gin + SQLite (GORM)** 的网页网速测试服务,支持 **延迟、下载、上传** 三项测试,
测速结果自动入库并生成 **排行榜**(下载榜 / 上传榜 / 延迟榜)。
- 线上地址: https://speedtest.lmve.net
- 代码仓库: https://git.lmve.net/dsh/speedtest
- 技术栈: Go 1.25 / Gin / GORM / SQLite (CGO) / TOML 配置 / systemd / Caddy
## 功能特性
-**延迟测试**: 前端连续 10 次 ping,取中位数作为延迟、平均绝对偏差作为抖动
- ⬇️ **下载测试**: 固定测速 10 秒——负载根据实测速率自适应(每轮约 2 秒),
快速连接自动加大负载填满 10 秒,慢速连接用小负载同样 10 秒内完成
- ⬆️ **上传测试**: 同样的固定 10 秒自适应策略
- 🏆 **排行榜**: 单表同时展示延迟 / 下载 / 上传,**点击列头动态排序**(再点切换升降序,
延迟默认升序、速度默认降序);测速完成后**自动高亮"我的成绩"**(含真实名次,
localStorage 持久化,刷新页面仍高亮);公网 IP 打码,内网来源 IP 完整标注方便调试
- 🌐 **公网 IP 识别**: 服务器直接识别客户端真实 IP(Caddy `X-Real-IP`),
不依赖任何外部 IP 查询服务;路由器单向伪装/公网直连时即为真实公网 IP
- 🔒 **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,无外部依赖)
```
## 本地开发
```bash
# 编译(SQLite 依赖 CGO
CGO_ENABLED=1 go build -ldflags="-s -w" -o speedtest .
# 本地运行(可用 SPEEDTEST_CONFIG 覆盖配置路径,见 test.toml 示例)
SPEEDTEST_CONFIG=./test.toml ./speedtest
```
## 部署(生产)
```bash
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 反代配置
```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`(缺失项自动补全):
```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":...}` |
| 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, client_ip?, server_ip?}` |
| GET | `/api/rankings?sort=&order=&include_id=` | 排行榜单表:`sort` ∈ download/upload/latency`order` ∈ asc/desc`include_id` 附加指定记录(真实名次 + `is_mine` |
客户端 IP 由服务器直接识别(Caddy 注入的 `X-Real-IP`),前端不调用任何外部 IP 服务;
`client_ip` / `server_ip` 字段为 API 兼容保留(可选)。公网 IP 打码保护隐私;
NAT 场景下的内网来源 IP 在排行榜中完整标注,供站长调试区分设备。