xfy c0b7e30bf0 feat(config,loadbalance): 添加上游服务器参数和 random 负载均衡算法
Target 新增 MaxConns/MaxFails/FailTimeout/Backup/Down/ProxyURI 字段,
实现 IsAvailable/RecordFailure/RecordSuccess 软失败机制,
filterHealthy 支持备份服务器优先级选择,
新增 random(Power of Two Choices)负载均衡算法。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 11:28:02 +08:00

73 lines
1.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 {
available := filterHealthy(targets)
if len(available) == 0 {
return nil
}
if len(available) == 1 {
return available[0]
}
// Power of Two Choices
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 {
available := filterHealthyAndExclude(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
}