From 6546f4a9056a59834a8b84b784eca067473b4829 Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Fri, 2 Sep 2022 21:53:50 +0800 Subject: [PATCH] fix default selector --- config/parsing/parse.go | 12 ++++++++++-- go.mod | 3 +-- go.sum | 8 ++------ handler/http/handler.go | 2 ++ internal/util/selector/key.go | 27 +++++++++++++++++++++++++++ selector/strategy.go | 28 ++++++++++++++++++++++++++++ 6 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 internal/util/selector/key.go diff --git a/config/parsing/parse.go b/config/parsing/parse.go index a12ad3b..d22b6f1 100644 --- a/config/parsing/parse.go +++ b/config/parsing/parse.go @@ -300,9 +300,17 @@ func ParseRecorder(cfg *config.RecorderConfig) (r recorder.Recorder) { } func defaultNodeSelector() selector.Selector[*chain.Node] { - return xs.NewSelector(xs.RoundRobinStrategy[*chain.Node]()) + return xs.NewSelector( + xs.RoundRobinStrategy[*chain.Node](), + xs.FailFilter[*chain.Node](xs.DefaultMaxFails, xs.DefaultFailTimeout), + xs.BackupFilter[*chain.Node](), + ) } func defaultChainSelector() selector.Selector[chain.SelectableChainer] { - return xs.NewSelector(xs.RoundRobinStrategy[chain.SelectableChainer]()) + return xs.NewSelector( + xs.RoundRobinStrategy[chain.SelectableChainer](), + xs.FailFilter[chain.SelectableChainer](xs.DefaultMaxFails, xs.DefaultFailTimeout), + xs.BackupFilter[chain.SelectableChainer](), + ) } diff --git a/go.mod b/go.mod index f02e8ae..939674f 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/gin-contrib/cors v1.3.1 github.com/gin-gonic/gin v1.7.7 - github.com/go-gost/core v0.0.0-20220831020931-e77908a89e63 + github.com/go-gost/core v0.0.0-20220902092328-713671067369 github.com/go-gost/gosocks4 v0.0.1 github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7 @@ -76,7 +76,6 @@ require ( github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect - github.com/smallnest/weighted v0.0.0-20201102054551-85ac5c79528c // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/cast v1.4.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect diff --git a/go.sum b/go.sum index 2569d79..df6283b 100644 --- a/go.sum +++ b/go.sum @@ -96,8 +96,8 @@ github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gost/core v0.0.0-20220831020931-e77908a89e63 h1:3IjymE34G/oU0s/rc9KlSOUw+bIEkmNtEuw62INqV2Q= -github.com/go-gost/core v0.0.0-20220831020931-e77908a89e63/go.mod h1:bHVbCS9da6XtKNYMkMUVcck5UqDDUkyC37erVfs4GXQ= +github.com/go-gost/core v0.0.0-20220902092328-713671067369 h1:qPZgaT7p3WP06X0uVGv5bVxD2DUP7x+RiMaYxJyQuwI= +github.com/go-gost/core v0.0.0-20220902092328-713671067369/go.mod h1:bHVbCS9da6XtKNYMkMUVcck5UqDDUkyC37erVfs4GXQ= github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s= github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc= github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 h1:A95M6UWcfZgOuJkQ7QLfG0Hs5peWIUSysCDNz4pfe04= @@ -335,8 +335,6 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smallnest/weighted v0.0.0-20201102054551-85ac5c79528c h1:XBpqxCr2X2HYZMOA+HTDhj8njR4PGhsK+M+geaMAQ20= -github.com/smallnest/weighted v0.0.0-20201102054551-85ac5c79528c/go.mod h1:xc9CoZ+ZBGwajnWto5Aqw/wWg8euy4HtOr6K9Fxp9iw= github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8= github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -424,8 +422,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 h1:tnebWN09GYg9OLPss1KXj8txwZc6X6uMr6VFdcGNbHw= golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= diff --git a/handler/http/handler.go b/handler/http/handler.go index 53cb47f..2cda386 100644 --- a/handler/http/handler.go +++ b/handler/http/handler.go @@ -61,6 +61,8 @@ func (h *httpHandler) Init(md md.Metadata) error { func (h *httpHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) error { defer conn.Close() + // ctx = sx.ContextWithHash(ctx, &sx.Hash{}) + start := time.Now() log := h.options.Logger.WithFields(map[string]any{ "remote": conn.RemoteAddr().String(), diff --git a/internal/util/selector/key.go b/internal/util/selector/key.go new file mode 100644 index 0000000..d90fa8e --- /dev/null +++ b/internal/util/selector/key.go @@ -0,0 +1,27 @@ +package selector + +import ( + "context" +) + +type hashKey struct{} + +type Hash struct { + Source string + Value int +} + +var ( + clientHashKey = &hashKey{} +) + +func ContextWithHash(ctx context.Context, hash *Hash) context.Context { + return context.WithValue(ctx, clientHashKey, hash) +} + +func HashFromContext(ctx context.Context) *Hash { + if v, _ := ctx.Value(clientHashKey).(*Hash); v != nil { + return v + } + return nil +} diff --git a/selector/strategy.go b/selector/strategy.go index fc57b58..579df8a 100644 --- a/selector/strategy.go +++ b/selector/strategy.go @@ -2,11 +2,14 @@ package selector import ( "context" + "math/rand" "sync" "sync/atomic" + "time" mdutil "github.com/go-gost/core/metadata/util" "github.com/go-gost/core/selector" + sx "github.com/go-gost/x/internal/util/selector" ) type roundRobinStrategy[T selector.Selectable] struct { @@ -77,3 +80,28 @@ func (s *fifoStrategy[T]) Apply(ctx context.Context, vs ...T) (v T) { } return vs[0] } + +type hashStrategy[T selector.Selectable] struct { + r *rand.Rand + mu sync.Mutex +} + +func HashStrategy[T selector.Selectable]() selector.Strategy[T] { + return &hashStrategy[T]{ + r: rand.New(rand.NewSource(time.Now().UnixNano())), + } +} + +func (s *hashStrategy[T]) Apply(ctx context.Context, vs ...T) (v T) { + if len(vs) == 0 { + return + } + if h := sx.HashFromContext(ctx); h != nil { + return vs[h.Value%len(vs)] + } + + s.mu.Lock() + defer s.mu.Unlock() + + return vs[s.r.Intn(len(vs))] +}