Files
rustfs/docs/operations/issue-713-gt1g-get-ops-guide-zh.md
T
houseme 96b1f5c373 feat(storage): optimize gt1g get read path (#3860)
* feat(storage): tune gt1g get read path

* docs(ops): add gt1g get benchmark guide

* feat(scripts): add gt1g get fallback runner

* test(storage): trim gt1g get helper warnings

* test(storage): reduce gt1g get helper type complexity
2026-06-25 20:12:08 +08:00

259 lines
5.9 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.
# Issue #713 `>1GiB GET` 优化与验证手册
## 1. 目标
本文用于收口 `backlog#713` 当前这一轮 `>1GiB GET` 优化的实现点与验证方式。
当前这轮改动先解决三件事:
1. `sequential hint` 真正参与 GET I/O 策略计算
2. storage media buffer cap 不再被统一的 `1MiB` hard clamp 二次截断
3. `>1GiB`、非 range、允许 readahead 的 streaming GET,会走更大的 stream buffer 策略
## 2. 当前代码行为变化
### 2.1 多因素调度
涉及:
1. `rustfs/src/storage/concurrency/io_schedule.rs`
当前行为:
1. `IoSchedulingContext.is_sequential_hint=true` 时,会优先按 `Sequential` 模式参与 buffer / readahead 决策
2. storage profile 提供的 media cap 现在可以真实生效
3. 例如默认常量下:
- `NVMe`: `2MiB`
- `SSD`: `1MiB`
- `HDD`: `512KiB`
### 2.2 GET body stream 策略
涉及:
1. `rustfs/src/app/object_usecase.rs`
当前行为:
1. `optimal_buffer_size` 不再被额外 `min(base_buffer_size)` 压回去
2. `>1GiB`、非 range、`enable_readahead=true` 的 streaming GET,会命中:
- `large_sequential_readahead`
3. 该路径当前把 `ReaderStream` buffer 扩到:
- `min(optimal_buffer_size * 2, 4MiB)`
### 2.3 GET observability
涉及:
1. `crates/io-metrics/src/lib.rs`
新增:
1. `rustfs_io_get_object_stream_strategy_total{strategy=...}`
2. `rustfs_io_get_object_stream_buffer_size_bytes{strategy=...}`
3. `rustfs_io_get_object_stream_response_size_bytes{strategy=...}`
当前策略标签:
1. `standard`
2. `large_sequential_readahead`
## 3. 推荐验证顺序
按下面顺序做最稳妥:
1. 先准备 plain `1GiB` / `2GiB` 对象
2. 先跑 `sequential` baseline
3. 再跑 `ranged_parallel`
4. 最后再决定是否继续补 encrypted / compressed
## 4. 准备测试对象
直接使用:
1. `scripts/prepare_gt1g_get_test_objects.sh`
示例:
```bash
bash scripts/prepare_gt1g_get_test_objects.sh \
--endpoint http://127.0.0.1:9000 \
--access-key rustfsadmin \
--secret-key rustfsadmin \
--bucket rustfs-bench \
--prefix bench/issue713/plain
```
默认会准备:
1. `1GiB=plain-1g.bin`
2. `2GiB=plain-2g.bin`
默认最终对象路径:
1. `s3://rustfs-bench/bench/issue713/plain/plain-1g.bin`
2. `s3://rustfs-bench/bench/issue713/plain/plain-2g.bin`
## 5. 执行 GET 矩阵
直接使用:
1. `scripts/run_gt1g_get_http_matrix.sh`
这个脚本特点:
1. 不把响应体落到本地磁盘
2. 直接把 body 丢到 `/dev/null`
3.`curl``size_download` 做字节校验和吞吐计算
4. 同时支持:
- `sequential`
- `ranged_parallel`
补充说明:
1. 如果本机没有 `mc`,脚本会自动 fallback 到仓库内置的 `rustfs/tests/gt1g_get_benchmark_tool.rs`
2. fallback 模式下,结果目录会落在:
- `rustfs/target/bench/...`
3. 非 fallback 模式下,结果目录仍按脚本参数落在:
- `target/bench/...`
### 5.1 baselinesequential + ranged_parallel
```bash
bash scripts/run_gt1g_get_http_matrix.sh \
--endpoint http://127.0.0.1:9000 \
--access-key rustfsadmin \
--secret-key rustfsadmin \
--bucket rustfs-bench \
--objects '1GiB=bench/issue713/plain/plain-1g.bin,2GiB=bench/issue713/plain/plain-2g.bin' \
--modes sequential,ranged_parallel \
--concurrencies 1,4,8 \
--range-workers 4 \
--rounds 3 \
--cooldown-secs 20
```
### 5.2 只跑 sequential
```bash
bash scripts/run_gt1g_get_http_matrix.sh \
--endpoint http://127.0.0.1:9000 \
--access-key rustfsadmin \
--secret-key rustfsadmin \
--bucket rustfs-bench \
--objects '1GiB=bench/issue713/plain/plain-1g.bin,2GiB=bench/issue713/plain/plain-2g.bin' \
--modes sequential \
--concurrencies 1,4,8 \
--rounds 3 \
--cooldown-secs 20
```
### 5.3 只跑 ranged_parallel
```bash
bash scripts/run_gt1g_get_http_matrix.sh \
--endpoint http://127.0.0.1:9000 \
--access-key rustfsadmin \
--secret-key rustfsadmin \
--bucket rustfs-bench \
--objects '1GiB=bench/issue713/plain/plain-1g.bin,2GiB=bench/issue713/plain/plain-2g.bin' \
--modes ranged_parallel \
--concurrencies 1,4,8 \
--range-workers 4,8 \
--rounds 3 \
--cooldown-secs 20
```
## 6. 输出目录
默认输出:
```text
target/bench/gt1g-get-http-<timestamp>/
```
重点看:
1. `round_results.csv`
2. `median_summary.csv`
3. `logs/`
`round_results.csv` 字段:
1. `object_label`
2. `object_key`
3. `mode`
4. `range_workers`
5. `concurrency`
6. `round`
7. `status`
8. `total_bytes`
9. `elapsed_ms`
10. `throughput_bps`
11. `avg_client_latency_ms`
## 7. 当前推荐观察点
### 7.1 sequential 是否命中大对象策略
查询:
```promql
sum by (strategy) (
increase(rustfs_io_get_object_stream_strategy_total[5m])
)
```
预期:
1. `>1GiB` 顺序 GET 应出现 `large_sequential_readahead`
### 7.2 GET stream buffer 分布
```promql
histogram_quantile(
0.95,
sum by (strategy, le) (
rate(rustfs_io_get_object_stream_buffer_size_bytes_bucket[5m])
)
)
```
### 7.3 GET 端到端完成时长
```promql
histogram_quantile(
0.95,
sum by (le) (
rate(rustfs_io_get_object_total_duration_seconds_bucket[5m])
)
)
```
## 8. 当前判断建议
如果 sequential 在 `1GiB/2GiB``c1` 下仍然没有明显优于旧结果,优先检查:
1. `large_sequential_readahead` 是否真的命中
2. buffer size 是否仍停在 `1MiB`
3. 请求是否实际是 range / encrypted / compressed,从而没走当前优化路径
如果 ranged_parallel 明显优于 sequential,再继续补:
1. 客户端并行分片数建议
2. plain 与 encrypted/compressed 的拆分对比
## 9. 当前边界
这轮实现还没有直接覆盖:
1. encrypted `>1GiB GET` 的单独 read-ahead 策略
2. compressed `>1GiB GET` 的专门 index / range 成本优化
3. server-side 主动预取缓存
因此当前更适合先做:
1. plain sequential vs ranged_parallel 基线
2. 命中策略与吞吐结果收敛
3. 再决定下一刀是否继续进 encrypted / compressed