@@ -24,7 +24,7 @@ import (
2424)
2525
2626const (
27- RTTEwmaDecay = 10 .0
27+ RTTEwmaDecay = 15 .0
2828)
2929
3030type RegisteredServer struct {
@@ -67,6 +67,7 @@ type ServerInfo struct {
6767
6868type LBStrategy interface {
6969 getCandidate (serversCount int ) int
70+ getActiveCount (serversCount int ) int
7071}
7172
7273type LBStrategyP2 struct {}
@@ -75,30 +76,50 @@ func (LBStrategyP2) getCandidate(serversCount int) int {
7576 return rand .Intn (Min (serversCount , 2 ))
7677}
7778
79+ func (LBStrategyP2 ) getActiveCount (serversCount int ) int {
80+ return Min (serversCount , 2 )
81+ }
82+
7883type LBStrategyPN struct { n int }
7984
8085func (s LBStrategyPN ) getCandidate (serversCount int ) int {
8186 return rand .Intn (Min (serversCount , s .n ))
8287}
8388
89+ func (s LBStrategyPN ) getActiveCount (serversCount int ) int {
90+ return Min (serversCount , s .n )
91+ }
92+
8493type LBStrategyPH struct {}
8594
8695func (LBStrategyPH ) getCandidate (serversCount int ) int {
8796 return rand .Intn (Max (Min (serversCount , 2 ), serversCount / 2 ))
8897}
8998
99+ func (LBStrategyPH ) getActiveCount (serversCount int ) int {
100+ return Max (Min (serversCount , 2 ), serversCount / 2 )
101+ }
102+
90103type LBStrategyFirst struct {}
91104
92105func (LBStrategyFirst ) getCandidate (int ) int {
93106 return 0
94107}
95108
109+ func (LBStrategyFirst ) getActiveCount (int ) int {
110+ return 1
111+ }
112+
96113type LBStrategyRandom struct {}
97114
98115func (LBStrategyRandom ) getCandidate (serversCount int ) int {
99116 return rand .Intn (serversCount )
100117}
101118
119+ func (LBStrategyRandom ) getActiveCount (serversCount int ) int {
120+ return serversCount
121+ }
122+
102123var DefaultLBStrategy = LBStrategyP2 {}
103124
104125type DNSCryptRelay struct {
@@ -227,29 +248,30 @@ func (serversInfo *ServersInfo) refresh(proxy *Proxy) (int, error) {
227248
228249func (serversInfo * ServersInfo ) estimatorUpdate () {
229250 // serversInfo.RWMutex is assumed to be Locked
230- candidate := rand .Intn (len (serversInfo .inner ))
231- if candidate == 0 {
251+ serversCount := len (serversInfo .inner )
252+ activeCount := serversInfo .lbStrategy .getActiveCount (serversCount )
253+ if activeCount == serversCount {
232254 return
233255 }
234- candidateRtt , currentBestRtt := serversInfo .inner [candidate ].rtt .Value (), serversInfo .inner [0 ].rtt .Value ()
235- if currentBestRtt < 0 {
236- currentBestRtt = candidateRtt
237- serversInfo .inner [0 ].rtt .Set (currentBestRtt )
256+ candidate , currentActive := rand .Intn (serversCount - activeCount )+ activeCount , rand .Intn (activeCount )
257+ candidateRtt , currentActiveRtt := serversInfo .inner [candidate ].rtt .Value (), serversInfo .inner [currentActive ].rtt .Value ()
258+ if currentActiveRtt < 0 {
259+ currentActiveRtt = candidateRtt
260+ serversInfo .inner [currentActive ].rtt .Set (currentActiveRtt )
238261 }
239262 partialSort := false
240- if candidateRtt < currentBestRtt {
241- serversInfo .inner [candidate ], serversInfo .inner [0 ] = serversInfo .inner [0 ], serversInfo .inner [candidate ]
263+ if candidateRtt < currentActiveRtt {
264+ serversInfo .inner [candidate ], serversInfo .inner [currentActive ] = serversInfo .inner [currentActive ], serversInfo .inner [candidate ]
265+ dlog .Debugf ("New preferred candidate: %s (RTT: %d vs previous: %d)" , serversInfo .inner [currentActive ].Name , int (candidateRtt ), int (currentActiveRtt ))
242266 partialSort = true
243- dlog .Debugf ("New preferred candidate: %v (rtt: %d vs previous: %d)" , serversInfo .inner [0 ].Name , int (candidateRtt ), int (currentBestRtt ))
244- } else if candidateRtt > 0 && candidateRtt >= currentBestRtt * 4.0 {
267+ } else if candidateRtt > 0 && candidateRtt > serversInfo .inner [activeCount ].rtt .Value () {
245268 if time .Since (serversInfo .inner [candidate ].lastActionTS ) > time .Duration (1 * time .Minute ) {
246- serversInfo .inner [candidate ].rtt .Add (MinF ( MaxF ( candidateRtt / 2.0 , currentBestRtt * 2.0 ), candidateRtt ))
247- dlog .Debugf ("Giving a new chance to candidate [%s], lowering its RTT from %d to %d (best: %d)" , serversInfo .inner [candidate ].Name , int (candidateRtt ), int (serversInfo .inner [candidate ].rtt .Value ()), int (currentBestRtt ))
269+ serversInfo .inner [candidate ].rtt .Add (serversInfo . inner [ activeCount ]. rtt . Value ( ))
270+ dlog .Debugf ("Giving a new chance to candidate [%s], lowering its RTT from %d to %d (best: %d)" , serversInfo .inner [candidate ].Name , int (candidateRtt ), int (serversInfo .inner [candidate ].rtt .Value ()), int (serversInfo . inner [ 0 ]. rtt . Value () ))
248271 partialSort = true
249272 }
250273 }
251274 if partialSort {
252- serversCount := len (serversInfo .inner )
253275 for i := 1 ; i < serversCount ; i ++ {
254276 if serversInfo .inner [i - 1 ].rtt .Value () > serversInfo .inner [i ].rtt .Value () {
255277 serversInfo .inner [i - 1 ], serversInfo .inner [i ] = serversInfo .inner [i ], serversInfo .inner [i - 1 ]
0 commit comments