From 2ad20fff33affe81f995ebe2d8a088ce8bf49422 Mon Sep 17 00:00:00 2001 From: LiuChen <38660378+Mrliuch@users.noreply.github.com> Date: Tue, 26 May 2026 15:09:46 +0800 Subject: [PATCH] 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 --- pkg/hostman/storageman/imagecachemanager_local.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/hostman/storageman/imagecachemanager_local.go b/pkg/hostman/storageman/imagecachemanager_local.go index 243fa536b4..023530fae0 100644 --- a/pkg/hostman/storageman/imagecachemanager_local.go +++ b/pkg/hostman/storageman/imagecachemanager_local.go @@ -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) } } }