mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-13 21:54:13 +08:00
code optimize
This commit is contained in:
parent
3d44156b67
commit
5c2c76b85c
@ -14,7 +14,7 @@ var _ Balancer = (*rttBasedBalancer)(nil)
|
|||||||
|
|
||||||
// Balancer is interface for load balancers
|
// Balancer is interface for load balancers
|
||||||
type Balancer interface {
|
type Balancer interface {
|
||||||
Select() *Node
|
Pick() *Node
|
||||||
}
|
}
|
||||||
|
|
||||||
type rttBasedBalancer struct {
|
type rttBasedBalancer struct {
|
||||||
@ -49,7 +49,7 @@ func newRTTBasedBalancer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Select selects qualified nodes
|
// Select selects qualified nodes
|
||||||
func (s *rttBasedBalancer) Select() *Node {
|
func (s *rttBasedBalancer) Pick() *Node {
|
||||||
nodes := s.HealthCheck.NodesByCategory()
|
nodes := s.HealthCheck.NodesByCategory()
|
||||||
var candidates []*Node
|
var candidates []*Node
|
||||||
if len(nodes.Qualified) > 0 {
|
if len(nodes.Qualified) > 0 {
|
||||||
@ -62,7 +62,7 @@ func (s *rttBasedBalancer) Select() *Node {
|
|||||||
candidates = nodes.Untested
|
candidates = nodes.Untested
|
||||||
shuffleNodes(candidates)
|
shuffleNodes(candidates)
|
||||||
}
|
}
|
||||||
selects := pickNodes(
|
selects := selectNodes(
|
||||||
candidates, s.logger,
|
candidates, s.logger,
|
||||||
int(s.options.Pick.Expected), s.options.Pick.Baselines,
|
int(s.options.Pick.Expected), s.options.Pick.Baselines,
|
||||||
)
|
)
|
||||||
@ -73,62 +73,6 @@ func (s *rttBasedBalancer) Select() *Node {
|
|||||||
return selects[rand.Intn(count)]
|
return selects[rand.Intn(count)]
|
||||||
}
|
}
|
||||||
|
|
||||||
// pickNodes selects nodes according to Baselines and Expected Count.
|
|
||||||
//
|
|
||||||
// The strategy always improves network response speed, not matter which mode below is configurated.
|
|
||||||
// But they can still have different priorities.
|
|
||||||
//
|
|
||||||
// 1. Bandwidth priority: no Baseline + Expected Count > 0.: selects `Expected Count` of nodes.
|
|
||||||
// (one if Expected Count <= 0)
|
|
||||||
//
|
|
||||||
// 2. Bandwidth priority advanced: Baselines + Expected Count > 0.
|
|
||||||
// Select `Expected Count` amount of nodes, and also those near them according to baselines.
|
|
||||||
// In other words, it selects according to different Baselines, until one of them matches
|
|
||||||
// the Expected Count, if no Baseline matches, Expected Count applied.
|
|
||||||
//
|
|
||||||
// 3. Speed priority: Baselines + `Expected Count <= 0`.
|
|
||||||
// go through all baselines until find selects, if not, select none. Used in combination
|
|
||||||
// with 'balancer.fallbackTag', it means: selects qualified nodes or use the fallback.
|
|
||||||
func pickNodes(nodes []*Node, logger log.Logger, expected int, baselines []option.Duration) []*Node {
|
|
||||||
if len(nodes) == 0 {
|
|
||||||
// s.logger.Debug("no qualified nodes")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
expected2 := int(expected)
|
|
||||||
availableCount := len(nodes)
|
|
||||||
if expected2 > availableCount {
|
|
||||||
return nodes
|
|
||||||
}
|
|
||||||
|
|
||||||
if expected2 <= 0 {
|
|
||||||
expected2 = 1
|
|
||||||
}
|
|
||||||
if len(baselines) == 0 {
|
|
||||||
return nodes[:expected2]
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
// go through all base line until find expected selects
|
|
||||||
for _, b := range baselines {
|
|
||||||
baseline := time.Duration(b)
|
|
||||||
for i := 0; i < availableCount; i++ {
|
|
||||||
if nodes[i].Weighted > baseline {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
count = i + 1
|
|
||||||
}
|
|
||||||
// don't continue if find expected selects
|
|
||||||
if count >= expected2 {
|
|
||||||
logger.Debug("applied baseline: ", baseline)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if expected > 0 && count < expected2 {
|
|
||||||
count = expected2
|
|
||||||
}
|
|
||||||
return nodes[:count]
|
|
||||||
}
|
|
||||||
|
|
||||||
func sortNodes(nodes []*Node) {
|
func sortNodes(nodes []*Node) {
|
||||||
sort.Slice(nodes, func(i, j int) bool {
|
sort.Slice(nodes, func(i, j int) bool {
|
||||||
left := nodes[i]
|
left := nodes[i]
|
||||||
|
66
balancer/balancer_select.go
Normal file
66
balancer/balancer_select.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package balancer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/log"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
// selectNodes selects nodes according to Baselines and Expected Count.
|
||||||
|
//
|
||||||
|
// The strategy always improves network response speed, not matter which mode below is configurated.
|
||||||
|
// But they can still have different priorities.
|
||||||
|
//
|
||||||
|
// 1. Bandwidth priority: no Baseline + Expected Count > 0.: selects `Expected Count` of nodes.
|
||||||
|
// (one if Expected Count <= 0)
|
||||||
|
//
|
||||||
|
// 2. Bandwidth priority advanced: Baselines + Expected Count > 0.
|
||||||
|
// Select `Expected Count` amount of nodes, and also those near them according to baselines.
|
||||||
|
// In other words, it selects according to different Baselines, until one of them matches
|
||||||
|
// the Expected Count, if no Baseline matches, Expected Count applied.
|
||||||
|
//
|
||||||
|
// 3. Speed priority: Baselines + `Expected Count <= 0`.
|
||||||
|
// go through all baselines until find selects, if not, select none. Used in combination
|
||||||
|
// with 'balancer.fallbackTag', it means: selects qualified nodes or use the fallback.
|
||||||
|
func selectNodes(nodes []*Node, logger log.Logger, expected int, baselines []option.Duration) []*Node {
|
||||||
|
if len(nodes) == 0 {
|
||||||
|
// s.logger.Debug("no qualified nodes")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
expected2 := int(expected)
|
||||||
|
availableCount := len(nodes)
|
||||||
|
if expected2 > availableCount {
|
||||||
|
return nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected2 <= 0 {
|
||||||
|
expected2 = 1
|
||||||
|
}
|
||||||
|
if len(baselines) == 0 {
|
||||||
|
return nodes[:expected2]
|
||||||
|
}
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
// go through all base line until find expected selects
|
||||||
|
for _, b := range baselines {
|
||||||
|
baseline := time.Duration(b)
|
||||||
|
for i := 0; i < availableCount; i++ {
|
||||||
|
if nodes[i].Weighted > baseline {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
count = i + 1
|
||||||
|
}
|
||||||
|
// don't continue if find expected selects
|
||||||
|
if count >= expected2 {
|
||||||
|
if logger != nil {
|
||||||
|
logger.Debug("applied baseline: ", baseline)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if expected > 0 && count < expected2 {
|
||||||
|
count = expected2
|
||||||
|
}
|
||||||
|
return nodes[:count]
|
||||||
|
}
|
@ -129,7 +129,7 @@ func (s *Balancer) setBalancer(b balancer.Balancer) error {
|
|||||||
|
|
||||||
func (s *Balancer) pick() adapter.Outbound {
|
func (s *Balancer) pick() adapter.Outbound {
|
||||||
if s.Balancer != nil {
|
if s.Balancer != nil {
|
||||||
selected := s.Balancer.Select()
|
selected := s.Balancer.Pick()
|
||||||
if selected == nil {
|
if selected == nil {
|
||||||
return s.fallback
|
return s.fallback
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user