filterHealthy() allocated 2 slices (available + backups) per call. filterHealthyAndExclude() allocated 3 (adds excludeSet map). IPHash allocated fnv.New64a() object per call. All triggered on every request's LB selection. Changes: - Add filterContext struct holding reusable buffers, managed by sync.Pool - Replace filterHealthy → filterInto (writes into pooled buffers) - Replace filterHealthyAndExclude → filterIntoExcluding (pooled buffers) - Add inline fnvHash64a() to avoid fnv.New64a() heap allocation - Update all 6 balancer algorithms (RoundRobin, WeightedRoundRobin, LeastConnections, IPHash, Random, ConsistentHash) to use pooled filterContext via acquire/release pattern - ConsistentHash.SelectExcludingByKey also uses pool for targetSet - Remove buildExcludeSet (merged into filterIntoExcluding) Result: allocs/op reduced from 2-3 to 0-1 on all LB Select paths.
81 lines
2.0 KiB
Go
81 lines
2.0 KiB
Go
// Package loadbalance 提供多种负载均衡算法实现,支持随机、轮询、加权、一致性哈希等策略。
|
||
//
|
||
// 包含随机负载均衡算法相关的逻辑。
|
||
//
|
||
// 作者:xfy
|
||
package loadbalance
|
||
|
||
import (
|
||
"math/rand/v2"
|
||
"sync/atomic"
|
||
)
|
||
|
||
// Random 实现随机负载均衡(Power of Two Choices 算法)。
|
||
//
|
||
// 随机选择两个候选目标,从中选择连接数较少的那个。
|
||
// 相比纯随机,Power of Two Choices 能更好地均衡负载,
|
||
// 同时保持 O(1) 的选择复杂度。
|
||
//
|
||
// 当只有一个候选目标时直接返回;当 MaxConns 限制生效时
|
||
// 自动跳过已满的目标。
|
||
type Random struct{}
|
||
|
||
// NewRandom 创建一个新的随机负载均衡器。
|
||
func NewRandom() *Random {
|
||
return &Random{}
|
||
}
|
||
|
||
// Select 使用 Power of Two Choices 算法选择目标。
|
||
// 随机选择两个候选,返回连接数较少的那个。
|
||
// 只考虑可用目标。如果没有可用目标则返回 nil。
|
||
func (r *Random) Select(targets []*Target) *Target {
|
||
fc := acquireFilterContext()
|
||
defer releaseFilterContext(fc)
|
||
available := filterInto(fc, targets)
|
||
if len(available) == 0 {
|
||
return nil
|
||
}
|
||
|
||
if len(available) == 1 {
|
||
return available[0]
|
||
}
|
||
|
||
i := rand.IntN(len(available))
|
||
j := rand.IntN(len(available) - 1)
|
||
if j >= i {
|
||
j++
|
||
}
|
||
|
||
a, b := available[i], available[j]
|
||
if atomic.LoadInt64(&a.Connections) <= atomic.LoadInt64(&b.Connections) {
|
||
return a
|
||
}
|
||
return b
|
||
}
|
||
|
||
// SelectExcluding 使用 Power of Two Choices 算法选择目标,排除指定的目标列表。
|
||
func (r *Random) SelectExcluding(targets []*Target, excluded []*Target) *Target {
|
||
fc := acquireFilterContext()
|
||
defer releaseFilterContext(fc)
|
||
available := filterIntoExcluding(fc, targets, excluded)
|
||
if len(available) == 0 {
|
||
return nil
|
||
}
|
||
|
||
if len(available) == 1 {
|
||
return available[0]
|
||
}
|
||
|
||
i := rand.IntN(len(available))
|
||
j := rand.IntN(len(available) - 1)
|
||
if j >= i {
|
||
j++
|
||
}
|
||
|
||
a, b := available[i], available[j]
|
||
if atomic.LoadInt64(&a.Connections) <= atomic.LoadInt64(&b.Connections) {
|
||
return a
|
||
}
|
||
return b
|
||
}
|