fix: throttle image cache progress callback to avoid download bottleneck (#24898)

When using S3/MinIO backend, the progress callback in AcquireImage was
called synchronously on every 4KB read chunk (via StreamPipe2). Each
call invokes UpdateServerProgress which makes a blocking HTTP PUT to the
compute API (~50ms), capping download speed at ~0.65 Mbps regardless of
available bandwidth.

Fix: throttle the callback to fire at most once every 5 seconds and make
the HTTP call asynchronous (goroutine), matching the behavior of v3.11.x
which used a 1-second ticker with async callbacks.

Fixes #24897

Co-authored-by: Mrliuch <liu15094534492@gmail.com>
This commit is contained in:
LiuChen
2026-05-26 15:09:46 +08:00
committed by GitHub
parent 52f84f0cd3
commit 2ad20fff33

View File

@@ -18,6 +18,7 @@ import (
"context"
"os"
"sync"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -113,9 +114,11 @@ func (c *SLocalImageCacheManager) AcquireImage(ctx context.Context, input api.Ca
c.cachedImages.Store(input.ImageId, imgObj)
}
if callback == nil && len(input.ServerId) > 0 {
var lastReport time.Time
callback = func(progress, progressMbps float64, totalSizeMb int64) {
if len(input.ServerId) > 0 {
hostutils.UpdateServerProgress(ctx, input.ServerId, progress, progressMbps)
if len(input.ServerId) > 0 && time.Since(lastReport) > 5*time.Second {
lastReport = time.Now()
go hostutils.UpdateServerProgress(ctx, input.ServerId, progress, progressMbps)
}
}
}