Compare commits

...

4 Commits

Author SHA1 Message Date
Aubrey Yang
00d58f9972
Merge 256e9d8c3d into 50d60cb004 2024-06-11 21:07:44 +08:00
xishang0128
50d60cb004 chore: Disable the loop back detector for CMFA 2024-06-11 20:52:41 +08:00
Aubrey Yang
256e9d8c3d
Update loadbalance.go 2024-04-17 18:21:59 +09:00
Aubrey Yang
828ba83ef3
Optimizations on the Round Robin strategies
Implemented optimizations on the Round Robin proxy selection strategies to enhance performance and stability under varying network conditions and proxy availabilities.

Dynamic Update Mechanism: Integrated an event-driven approach that triggers the proxy list update process when significant changes in proxy status are detected, rather than on every touch.

Memory and Performance: Optimized the management of the available proxies list to update in-place where possible.

Load Distribution: Improved the fairness in proxy usage by introducing a weighted round-robin mechanism that accounts for proxy response times and error rates, ensuring a more balanced load across the proxies.
2024-04-17 18:20:30 +09:00
2 changed files with 26 additions and 21 deletions

View File

@ -10,6 +10,7 @@ import (
"github.com/metacubex/mihomo/component/loopback" "github.com/metacubex/mihomo/component/loopback"
"github.com/metacubex/mihomo/component/resolver" "github.com/metacubex/mihomo/component/resolver"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/constant/features"
) )
type Direct struct { type Direct struct {
@ -24,8 +25,10 @@ type DirectOption struct {
// DialContext implements C.ProxyAdapter // DialContext implements C.ProxyAdapter
func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) { func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
if err := d.loopBack.CheckConn(metadata); err != nil { if !features.CMFA {
return nil, err if err := d.loopBack.CheckConn(metadata); err != nil {
return nil, err
}
} }
opts = append(opts, dialer.WithResolver(resolver.DefaultResolver)) opts = append(opts, dialer.WithResolver(resolver.DefaultResolver))
c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress(), d.Base.DialOptions(opts...)...) c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress(), d.Base.DialOptions(opts...)...)
@ -38,8 +41,10 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
// ListenPacketContext implements C.ProxyAdapter // ListenPacketContext implements C.ProxyAdapter
func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) { func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
if err := d.loopBack.CheckPacketConn(metadata); err != nil { if !features.CMFA {
return nil, err if err := d.loopBack.CheckPacketConn(metadata); err != nil {
return nil, err
}
} }
// net.UDPConn.WriteTo only working with *net.UDPAddr, so we need a net.UDPAddr // net.UDPConn.WriteTo only working with *net.UDPAddr, so we need a net.UDPAddr
if !metadata.Resolved() { if !metadata.Resolved() {

View File

@ -5,8 +5,8 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"net"
"sync" "sync"
"net"
"time" "time"
"github.com/metacubex/mihomo/adapter/outbound" "github.com/metacubex/mihomo/adapter/outbound"
@ -134,31 +134,31 @@ func (lb *LoadBalance) IsL3Protocol(metadata *C.Metadata) bool {
} }
func strategyRoundRobin(url string) strategyFn { func strategyRoundRobin(url string) strategyFn {
var availableProxies []C.Proxy
idx := 0 idx := 0
idxMutex := sync.Mutex{} idxMutex := sync.Mutex{}
return func(proxies []C.Proxy, metadata *C.Metadata, touch bool) C.Proxy { return func(proxies []C.Proxy, metadata *C.Metadata, touch bool) C.Proxy {
idxMutex.Lock() idxMutex.Lock()
defer idxMutex.Unlock() defer idxMutex.Unlock()
i := 0
length := len(proxies)
if touch { if touch {
defer func() { // check list
idx = (idx + i) % length availableProxies = []C.Proxy{}
}() for _, proxy := range proxies {
} if proxy.AliveForTestUrl(url) {
availableProxies = append(availableProxies, proxy)
for ; i < length; i++ { }
id := (idx + i) % length }
proxy := proxies[id] // fallback
if proxy.AliveForTestUrl(url) { if len(availableProxies) == 0 {
i++ return proxies[0]
return proxy
} }
} }
proxy := availableProxies[idx]
return proxies[0] // reset idx
idx = (idx + 1) % len(availableProxies)
return proxy
} }
} }