mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-06-05 22:44:17 +00:00
HTTP Client Optimization:
Reduced connection timeouts from 30s to 15s Decreased idle connection limits from 100 to 30 Lowered keepalive duration from 90s to 30s Added MaxConnsPerHost limit of 50 to prevent connection flooding Optimized TLS handshake timeout to 5s Cache System Optimization: Implemented size-limited LRU cache with max 1000 items Added efficient eviction of least recently used items Improved cleanup process with batch operations Reduced lock contention by splitting read/write operations Optimized memory usage with access tracking Added immediate cleanup of expired items during access Connection Management: Enabled connection reuse with keepalives Reduced connection pool size to conserve memory Implemented more aggressive connection timeout Added connection limits per host to prevent resource exhaustion
This commit is contained in:
@@ -24,13 +24,24 @@ type Cache struct {
|
||||
// mutex protects concurrent access to the items map
|
||||
// Use RLock/RUnlock for reads and Lock/Unlock for writes
|
||||
mutex sync.RWMutex
|
||||
|
||||
// maxSize is the maximum number of items allowed in the cache
|
||||
maxSize int
|
||||
|
||||
// accessList maintains the order of item access for eviction
|
||||
accessList []string
|
||||
}
|
||||
|
||||
// DefaultMaxSize is the default maximum number of items in the cache
|
||||
const DefaultMaxSize = 1000
|
||||
|
||||
// NewCache creates a new empty cache instance.
|
||||
// The cache is immediately ready for use and is thread-safe.
|
||||
func NewCache() *Cache {
|
||||
return &Cache{
|
||||
items: make(map[string]CacheItem),
|
||||
items: make(map[string]CacheItem),
|
||||
maxSize: DefaultMaxSize,
|
||||
accessList: make([]string, 0, DefaultMaxSize),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,10 +54,27 @@ func NewCache() *Cache {
|
||||
func (c *Cache) Set(key string, value interface{}, expiration time.Duration) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
// If key exists, update it
|
||||
if _, exists := c.items[key]; exists {
|
||||
c.items[key] = CacheItem{
|
||||
Value: value,
|
||||
ExpiresAt: time.Now().Add(expiration),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// If cache is full, remove oldest item
|
||||
if len(c.items) >= c.maxSize {
|
||||
c.evictOldest()
|
||||
}
|
||||
|
||||
// Add new item
|
||||
c.items[key] = CacheItem{
|
||||
Value: value,
|
||||
ExpiresAt: time.Now().Add(expiration),
|
||||
}
|
||||
c.accessList = append(c.accessList, key)
|
||||
}
|
||||
|
||||
// Get retrieves an item from the cache if it exists and hasn't expired.
|
||||
@@ -58,15 +86,25 @@ func (c *Cache) Set(key string, value interface{}, expiration time.Duration) {
|
||||
// Thread-safe: Uses read locking to ensure safe concurrent access.
|
||||
func (c *Cache) Get(key string) (interface{}, bool) {
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
item, found := c.items[key]
|
||||
c.mutex.RUnlock()
|
||||
|
||||
if !found {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if time.Now().After(item.ExpiresAt) {
|
||||
delete(c.items, key)
|
||||
c.mutex.Lock()
|
||||
c.removeItem(key)
|
||||
c.mutex.Unlock()
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Update access order
|
||||
c.mutex.Lock()
|
||||
c.updateAccessOrder(key)
|
||||
c.mutex.Unlock()
|
||||
|
||||
return item.Value, true
|
||||
}
|
||||
|
||||
@@ -86,10 +124,46 @@ func (c *Cache) Delete(key string) {
|
||||
func (c *Cache) Cleanup() {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
for key, item := range c.items {
|
||||
if now.After(item.ExpiresAt) {
|
||||
var newAccessList []string
|
||||
|
||||
for _, key := range c.accessList {
|
||||
if item, exists := c.items[key]; exists && !now.After(item.ExpiresAt) {
|
||||
newAccessList = append(newAccessList, key)
|
||||
} else {
|
||||
delete(c.items, key)
|
||||
}
|
||||
}
|
||||
|
||||
c.accessList = newAccessList
|
||||
}
|
||||
|
||||
// evictOldest removes the least recently used item from the cache
|
||||
func (c *Cache) evictOldest() {
|
||||
if len(c.accessList) > 0 {
|
||||
oldest := c.accessList[0]
|
||||
c.removeItem(oldest)
|
||||
}
|
||||
}
|
||||
|
||||
// removeItem removes an item from both the cache and access list
|
||||
func (c *Cache) removeItem(key string) {
|
||||
delete(c.items, key)
|
||||
for i, k := range c.accessList {
|
||||
if k == key {
|
||||
c.accessList = append(c.accessList[:i], c.accessList[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// updateAccessOrder moves the accessed key to the end of the access list
|
||||
func (c *Cache) updateAccessOrder(key string) {
|
||||
for i, k := range c.accessList {
|
||||
if k == key {
|
||||
c.accessList = append(append(c.accessList[:i], c.accessList[i+1:]...), key)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,17 +180,19 @@ func New(ctx context.Context, next http.Handler, config *Config, name string) (h
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
dialer := &net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
Timeout: 15 * time.Second, // Reduced timeout
|
||||
KeepAlive: 15 * time.Second, // Reduced keepalive
|
||||
}
|
||||
return dialer.DialContext(ctx, network, addr)
|
||||
},
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
TLSHandshakeTimeout: 5 * time.Second, // Reduced from 10s
|
||||
ExpectContinueTimeout: 0,
|
||||
MaxIdleConns: 100,
|
||||
MaxIdleConnsPerHost: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
MaxIdleConns: 30, // Reduced from 100
|
||||
MaxIdleConnsPerHost: 10, // Reduced from 100
|
||||
IdleConnTimeout: 30 * time.Second, // Reduced from 90s
|
||||
DisableKeepAlives: false, // Enable connection reuse
|
||||
MaxConnsPerHost: 50, // Limit max connections
|
||||
}
|
||||
|
||||
var httpClient *http.Client
|
||||
@@ -198,7 +200,7 @@ func New(ctx context.Context, next http.Handler, config *Config, name string) (h
|
||||
httpClient = config.HTTPClient
|
||||
} else {
|
||||
httpClient = &http.Client{
|
||||
Timeout: time.Second * 30,
|
||||
Timeout: time.Second * 15, // Reduced timeout
|
||||
Transport: transport,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user