mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-25 14:19:20 +02:00
fa5d7a255b
* v5: Health Check & LeastLoad Strategy (rebased from 2c5a71490368500a982018a74a6d519c7e121816) Some changes will be necessary to integrate it into V2Ray * Update proto * parse duration conf with time.Parse() * moving health ping to observatory as a standalone component * moving health ping to observatory as a standalone component: auto generated file * add initialization for health ping * incorporate changes in router implementation * support principle target output * add v4 json support for BurstObservatory & fix balancer reference * update API command * remove cancelled API * return zero length value when observer is not found * remove duplicated targeted dispatch * adjust test with updated structure * bug fix for observer * fix strategy selector * fix strategy least load * Fix ticker usage ticker.Close does not close ticker.C * feat: Replace default Health Ping URL to HTTPS (#1991) * fix selectLeastLoad() returns wrong number of nodes (#2083) * Test: fix leastload strategy unit test * fix(router): panic caused by concurrent map read and write (#2678) * Clean up code --------- Co-authored-by: Jebbs <qjebbs@gmail.com> Co-authored-by: Shelikhoo <xiaokangwang@outlook.com> Co-authored-by: 世界 <i@sekai.icu> Co-authored-by: Bernd Eichelberger <46166740+4-FLOSS-Free-Libre-Open-Source-Software@users.noreply.github.com> Co-authored-by: 秋のかえで <autmaple@protonmail.com> Co-authored-by: Rinka <kujourinka@gmail.com>
90 lines
2.0 KiB
Go
90 lines
2.0 KiB
Go
package router
|
|
|
|
import (
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
type weightScaler func(value, weight float64) float64
|
|
|
|
var numberFinder = regexp.MustCompile(`\d+(\.\d+)?`)
|
|
|
|
// NewWeightManager creates a new WeightManager with settings
|
|
func NewWeightManager(s []*StrategyWeight, defaultWeight float64, scaler weightScaler) *WeightManager {
|
|
return &WeightManager{
|
|
settings: s,
|
|
cache: make(map[string]float64),
|
|
scaler: scaler,
|
|
defaultWeight: defaultWeight,
|
|
}
|
|
}
|
|
|
|
// WeightManager manages weights for specific settings
|
|
type WeightManager struct {
|
|
settings []*StrategyWeight
|
|
cache map[string]float64
|
|
scaler weightScaler
|
|
defaultWeight float64
|
|
mu sync.Mutex
|
|
}
|
|
|
|
// Get get the weight of specified tag
|
|
func (s *WeightManager) Get(tag string) float64 {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
weight, ok := s.cache[tag]
|
|
if ok {
|
|
return weight
|
|
}
|
|
weight = s.findValue(tag)
|
|
s.cache[tag] = weight
|
|
return weight
|
|
}
|
|
|
|
// Apply applies weight to the value
|
|
func (s *WeightManager) Apply(tag string, value float64) float64 {
|
|
return s.scaler(value, s.Get(tag))
|
|
}
|
|
|
|
func (s *WeightManager) findValue(tag string) float64 {
|
|
for _, w := range s.settings {
|
|
matched := s.getMatch(tag, w.Match, w.Regexp)
|
|
if matched == "" {
|
|
continue
|
|
}
|
|
if w.Value > 0 {
|
|
return float64(w.Value)
|
|
}
|
|
// auto weight from matched
|
|
numStr := numberFinder.FindString(matched)
|
|
if numStr == "" {
|
|
return s.defaultWeight
|
|
}
|
|
weight, err := strconv.ParseFloat(numStr, 64)
|
|
if err != nil {
|
|
newError("unexpected error from ParseFloat: ", err).AtError().WriteToLog()
|
|
return s.defaultWeight
|
|
}
|
|
return weight
|
|
}
|
|
return s.defaultWeight
|
|
}
|
|
|
|
func (s *WeightManager) getMatch(tag, find string, isRegexp bool) string {
|
|
if !isRegexp {
|
|
idx := strings.Index(tag, find)
|
|
if idx < 0 {
|
|
return ""
|
|
}
|
|
return find
|
|
}
|
|
r, err := regexp.Compile(find)
|
|
if err != nil {
|
|
newError("invalid regexp: ", find, "err: ", err).AtError().WriteToLog()
|
|
return ""
|
|
}
|
|
return r.FindString(tag)
|
|
}
|