From 89b08ed0bf1610c03a9450ababa2f215afc36d94 Mon Sep 17 00:00:00 2001 From: rainsun Date: Wed, 13 Aug 2025 10:05:50 +0800 Subject: [PATCH] feat(registry): implement transport caching and clear cache on registry updates - Added transport caching to optimize HTTP transport reuse for registry endpoints. - Implemented ClearTransportCache function to clear the transport cache when registry configurations change, ensuring fresh transports are used. - Enhanced GetTransport method to utilize cached transports, improving performance and reducing overhead. Signed-off-by: rainsun --- registry-scanner/pkg/registry/config.go | 4 ++ registry-scanner/pkg/registry/endpoints.go | 61 ++++++++++++++++++++-- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/registry-scanner/pkg/registry/config.go b/registry-scanner/pkg/registry/config.go index 641c5987..53376b27 100644 --- a/registry-scanner/pkg/registry/config.go +++ b/registry-scanner/pkg/registry/config.go @@ -35,6 +35,10 @@ func clearRegistries() { registryLock.Lock() registries = make(map[string]*RegistryEndpoint) registryLock.Unlock() + + // Also clear transport cache when registries are cleared + // This ensures that when registry configuration changes, we use fresh transports + ClearTransportCache() } // LoadRegistryConfiguration loads a YAML-formatted registry configuration from diff --git a/registry-scanner/pkg/registry/endpoints.go b/registry-scanner/pkg/registry/endpoints.go index f0de871c..35c8810e 100644 --- a/registry-scanner/pkg/registry/endpoints.go +++ b/registry-scanner/pkg/registry/endpoints.go @@ -121,6 +121,10 @@ var registryLock sync.RWMutex // credentialGroup ensures only one credential refresh happens per registry var credentialGroup singleflight.Group +// Transport cache to avoid creating new transports for each request +var transportCache = make(map[string]*http.Transport) +var transportCacheLock sync.RWMutex + func AddRegistryEndpointFromConfig(epc RegistryConfiguration) error { ep := NewRegistryEndpoint(epc.Prefix, epc.Name, epc.ApiURL, epc.Credentials, epc.DefaultNS, epc.Insecure, TagListSortFromString(epc.TagSortMode), epc.Limit, epc.CredsExpire) return AddRegistryEndpoint(ep) @@ -282,16 +286,65 @@ func (ep *RegistryEndpoint) DeepCopy() *RegistryEndpoint { return newEp } +// ClearTransportCache clears the transport cache +// This is useful when registry configuration changes +func ClearTransportCache() { + transportCacheLock.Lock() + transportCache = make(map[string]*http.Transport) + transportCacheLock.Unlock() +} + // GetTransport returns a transport object for this endpoint -func (ep *RegistryEndpoint) GetTransport() *http.Transport { +// Implements connection pooling and reuse to avoid creating new transports for each request +func (ep *RegistryEndpoint) GetTransport() *http.Transport { + // Check if we have a cached transport for this registry + transportCacheLock.RLock() + if transport, exists := transportCache[ep.RegistryAPI]; exists { + log.Debugf("Transport cache HIT for %s: %p", ep.RegistryAPI, transport) + transportCacheLock.RUnlock() + return transport + } + log.Debugf("Transport cache MISS for %s", ep.RegistryAPI) + transportCacheLock.RUnlock() + + // Create a new transport with optimized connection pool settings + transportCacheLock.Lock() + defer transportCacheLock.Unlock() + + // Double-check after acquiring write lock + if transport, exists := transportCache[ep.RegistryAPI]; exists { + log.Debugf("Transport cache double-check HIT for %s: %p", ep.RegistryAPI, transport) + return transport + } + + log.Debugf("Creating NEW transport for %s", ep.RegistryAPI) + tlsC := &tls.Config{} if ep.Insecure { tlsC.InsecureSkipVerify = true } - return &http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSClientConfig: tlsC, + + // Create transport with aggressive timeout and connection management + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + TLSClientConfig: tlsC, + MaxIdleConns: 20, // Reduced global max idle connections + MaxIdleConnsPerHost: 5, // Reduced per-host connections + IdleConnTimeout: 30 * time.Second, // Reduced idle timeout + TLSHandshakeTimeout: 5 * time.Second, // Reduced TLS timeout + ExpectContinueTimeout: 1 * time.Second, // Expect-Continue timeout + DisableKeepAlives: false, // Enable HTTP Keep-Alive + ForceAttemptHTTP2: true, // Enable HTTP/2 if available + // Critical timeout settings to prevent hanging connections + ResponseHeaderTimeout: 10 * time.Second, // Response header timeout + MaxConnsPerHost: 10, // Limit total connections per host } + + // Cache the transport for reuse + transportCache[ep.RegistryAPI] = transport + log.Debugf("Cached NEW transport for %s: %p", ep.RegistryAPI, transport) + + return transport } // init initializes the registry configuration