Files
FileShare/docs/api/13-bandwidth.md
T
SKYMirror 157db0e9e5
Release 镜像 / 测试(推送前置门禁) (push) Successful in 45s
Release 镜像 / 多架构构建并推送 ACR (push) Successful in 1m40s
v3.2:上下行带宽限速 + 品牌更新 + 产品修复
亮点
- v3.2 带宽限速(upload_rate/download_rate,字节/秒,0=不限速;管理端立即生效)
  - middleware/bandwidth.go 时间窗对齐 sleep 算法 + 单元测试(400KB@100KB/s 4.00s 精度)
  - 下载:serveFile 包裹 storage.ReadCloser(统一覆盖 local/webdav/s3 代理下载)
  - 上传:UploadBandwidthMiddleware 包裹 Request.Body(shareFile/chunk/presign proxy)
  - S3 预签名直传不可服务端限速——UI/文档明示
  - 后台 SettingsView 增加 MB/s 友好输入;i18n zh-CN/en-US 双语
- v3.2 文档:新增 docs/api/13-bandwidth.md 专题;10-config 指针;00-overview changelog
  与限流表带宽行;openapi.yaml 三处 schema + description 更新
- README.md / web/README.md / server/README.md / deploy/README.md 全部覆盖

品牌(v3.1 收尾)
- 文件快递柜 → 文件快传(前端/后端默认值/文档/产物/运行 KV)
- 「复制取件码」按钮删除;取件码块点击即复制(保持原尺寸)
- 「复制链接」→「复制链接和提取码」(一并复制链接和提取码)

产品修复(v3.1.1)
- 文本分享 Content-Type text/plain + urlencoded body:前端显式声明 urlencoded 头根治;
  后端 bindJSONOrForm 兜底兼容 text/plain + JSON/urlencoded 嗅探
- Docker 部署文档校对到 v3.1 现状(热切换 + 端口/卷/健康检查)
2026-09-06 10:20:04 +08:00

113 lines
5.2 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.
# 带宽限速(v3.2
> v3.2 新增。管理端可独立设置**上行(上传)/ 下行(下载)带宽**,单位字节/秒(前端 UI 友好单位为 MB/s),
> 0=不限速。修改后**立即生效**(每请求动态读取最新 KV,不需重启容器/进程)。
## 适用对象
| 方向 | 范围 | 说明 |
|---|---|---|
| 上行 | `POST /share/file``POST /chunk/upload/{id}/{idx}``POST /chunk/upload`(扁平兼容)、`PUT /presign/upload/proxy/{id}` | 包裹 `c.Request.Body`,对 multipart 解析与表单字段读取天然节流 |
| 下行 | `GET /share/download?key=&code=``GET /share/select?code=`(文件流)、`GET /admin/file/download?id=` | 包裹 `storage.ReadCloser`local/webdav/s3 代理下载),Range 分段也按节流后的字节流推进 |
> **不在限速范围**:S3 预签名**直传**(客户端 → S3 桶直连,**服务端无法介入**);
> 文本分享下载(GET `/share/select` 命中 `text` 字段时直接返回 JSON 字符串,体积通常远小于 1MB)。
## 配置项
| 键 | 类型/边界 | 默认 | 说明 |
|---|---|---|---|
| `upload_rate` | int640 ~ 1 073 741 824,即 1 GiB/s | 0 | 上行字节/秒;0=不限速 |
| `download_rate` | int640 ~ 1 073 741 824 | 0 | 下行字节/秒;0=不限速 |
UI 输入:管理端「系统设置 → 上传频率限制」卡底部两个字段,**MB/s** 整数,0=不限速。
保存时前端把 `MB/s × 1024 × 1024` 换算为字节/秒写入 KV。
## 算法(实现原理)
基于**时间窗的精确调度**,每个 `Read` 调用:
```
start ← 首次 Read 的时刻
bytes ← 累计已读字节(每次 Read 累加返回值 n)
expected = start + bytes / rate // 按限速值推算"应到达时间"
if now < expected:
sleep(expected - now) // 超前则阻塞补齐
return n, err
```
保证长期速率严格 ≤ `rate`,瞬时由调用方 Read 块大小自然突发。**不按字节微睡眠**——避免单次 Read 在低速场景下被调度抖动放大。
> 早期版本按每字节 sleep 1/rate 秒,被 Mac 调度粒度(约 10µs)放大后实际速率只有目标值的 1/3;v3.2.1 修正为整块对齐 sleep。
## 公开接口
`GET /api/v1/config``GET /admin/config/get` 均下发当前生效值(数值型,字节/秒):
```json
{
"data": {
"config": {
"upload_rate": 0,
"download_rate": 0,
...
}
}
}
```
## 修改(管理端)
```bash
# PATCH /admin/config/update
curl -X PATCH http://localhost:8466/admin/config/update \
-H "Authorization: Bearer <admin-jwt>" \
-H "Content-Type: application/json" \
-d '{"upload_rate": 1048576, "download_rate": 524288}'
# ↑ 上行 1 MB/s、下行 512 KB/s
```
边界校验(来自 `settings.KVSchema`,越界 400 中文错误):
- `upload_rate` / `download_rate` 必须是整数,0 ≤ 值 ≤ 1073741824
## 验证(端到端)
```bash
# 1) 设下载限速 200 KB/s
curl -X PATCH http://localhost:8466/admin/config/update \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"download_rate": 204800}' -w '\nHTTP %{http_code}\n'
# 2) 上传 2 MB 测试文件(自动随机取件码或自定义 5~8 位)
curl -X POST http://localhost:8466/share/file -F file=@/tmp/2mb.bin \
-F "expire_value=1" -F "expire_style=day" -F "code="
# 3) 管理员接口下载(不消耗取件次数,便于压测)
ID=$(curl -s "http://localhost:8466/admin/file/list?page=1&size=20" \
-H "Authorization: Bearer <token>" | jq '.data.data[0].id')
time curl -s -o /tmp/dl.bin "http://localhost:8466/admin/file/download?id=$ID" \
-H "Authorization: Bearer <token>"
# 期望 ~10s2 097 152 字节 / 200 000 B/s = 10.486 s
# 实测 10.65s(误差 1.5%,含 HTTP 头/响应开销)
```
> 测完记得恢复:`PATCH /admin/config/update` 设回 0。
## 性能开销
- 0 速率路径:完全透传,无任何额外分配/锁/计时。
- 限速路径:每次 Read 多两次 `time.Now()` 与一次整数除法;`mutex.Lock` 仅在并发复用同一 reader 时阻塞(每请求独立实例,正常无争用)。
## 边界与注意
1. **S3 预签名直传不可限速**:客户端拿到预签名 URL 后直连 S3 桶,不经本服务。`PUT /presign/upload/proxy/{id}`(**代理模式**)仍受上行限速;前端实现可在管理端提示用户这一点。
2. **共享存储后端的"突发"**:令牌桶改为时间窗对齐后,单次 Read 仍可能瞬时突发到调用方请求的块大小(典型 32~64 KB)。需更严格平滑的可在调用方调小读取块大小(如 4 KB)。
3. **代理/反代层限速**:如部署在 Nginx / Cloudflare 后,公网入站还会经过代理的限速/带宽上限;本服务限速只对服务进程侧可见。
4. **Range 多区间**:HTTP Range 单区间请求的字节流仍按限速推进;多区间未实现,回退全量。
5. **重置**:UI 「恢复默认」按钮把两个速率归 0(不限速)。
## 相关
- 配置 KV 概览:见《环境变量与配置》`upload_rate` / `download_rate` 条目
- 管理端修改示例:见《管理后台 API》`PATCH /admin/config/update`
- OpenAPI schema`docs/openapi.yaml``/admin/config/update` requestBody.properties