cline optimization on range request and memory usage
All checks were successful
build container / build-container (push) Successful in 29m33s
run go test / test (push) Successful in 26m15s

This commit is contained in:
2025-06-10 17:44:44 +08:00
parent 147659b0da
commit 80560f7408
6 changed files with 952 additions and 440 deletions

View File

@ -23,20 +23,36 @@
### 2. 生产者-消费者模式 (Producer-Consumer)
在文件下载过程中,使用了生产者-消费者模式。
在文件下载和流式响应Ranged Request中,使用了生产者-消费者模式。
- **生产者**: `tryUpstream` 函数中的 goroutine 负责从上游服务器读取数据块chunk并将其放入一个 `chan Chunk` 中。
- **消费者**: `streamOnline` 函数中的代码从 `chan Chunk` 中读取数据,并执行两个操作:
1. 将数据写入 `bytes.Buffer`,供后续的请求者使用
2. 将数据写入本地临时文件,用于持久化缓存
- **生产者 (`startOrJoinStream`)**:
- 为每个首次请求的文件启动一个 goroutine。
- 负责从最快的上游服务器下载文件内容
- 将内容**直接写入一个临时文件** (`*os.File`) 中,而不是写入内存缓冲区
- 通过 `sync.Cond` 广播下载进度(已写入的字节数 `Offset`)。
- 下载成功后,将临时文件重命名为最终的缓存文件。
- **消费者 (`serveRangedRequest`)**:
- 当收到一个范围请求时,它会找到或等待对应的 `StreamObject`
- 为了安全地并发读取正在被生产者写入的文件,消费者会使用 `syscall.Dup()` **复制临时文件的文件描述符**
- 每个消费者都通过自己独立的、复制出来的文件句柄 (`*os.File`) 读取所需范围的数据,这避免了与生产者或其他消费者发生文件句柄状态的冲突。
- 消费者根据生产者的 `Offset` 进度和 `sync.Cond` 信号来等待其请求范围的数据变为可用。
### 3. 并发访问控制 (Mutex for Concurrent Access)
### 3. 并发访问控制与对象生命周期管理
为了处理多个客户端同时请求同一个文件的情况,系统使用了 `sync.Mutex` 和一个 `map[string]*StreamObject`
- 当第一个请求到达时,它会获得一个锁,并创建一个 `StreamObject` 来代表这个正在进行的下载任务。
- 后续对同一文件的请求会发现 `StreamObject` 已存在,它们不会再次向上游发起请求,而是会等待并从这个共享的 `StreamObject` 中读取数据
- 下载完成后,`StreamObject` 会从 map 中移除。
- 当第一个对某文件的请求(我们称之为“消费者”)到达时,它会获得一个锁,并创建一个 `StreamObject` 来代表这个正在进行的下载任务然后启动一个“生产者”goroutine 来执行下载
- 后续对同一文件的请求会发现 `StreamObject` 已存在于 map 中,它们不会再次启动下载,而是会共享这个对象
**`StreamObject` 生命周期管理 (基于 GC)**
我们采用了一种简洁且高效的、依赖 Go 语言垃圾回收GC的模式来管理 `StreamObject` 的生命周期:
1. **生产者负责移除**: 下载 goroutine生产者在完成其任务无论成功或失败其唯一的职责就是将 `StreamObject` 从全局的 `map[string]*StreamObject` 中移除。
2. **消费者持有引用**: 与此同时,所有正在处理该文件请求的 HTTP Handler消费者仍然持有对该 `StreamObject` 的引用。
3. **GC 自动回收**: 因为消费者们还持有引用Go 的 GC 不会回收这个对象。只有当最后一个消费者处理完请求、其函数栈帧销毁后,对 `StreamObject` 的最后一个引用才会消失。此时GC 会在下一次运行时自动回收该对象的内存。
这个模式避免了复杂的引用计数或定时器,代码更简洁,并且从根本上解决了之前因固定延迟导致的性能问题。
### 4. 中间件 (Middleware)