Skip to content

Commit

Permalink
Add randomness to server selection (#81)
Browse files Browse the repository at this point in the history
* add randomness to server selection

* change to request option
  • Loading branch information
frostbyte73 authored Jan 29, 2024
1 parent 829a885 commit 473b29c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 13 deletions.
7 changes: 7 additions & 0 deletions pkg/client/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ func getRequestOpts(i *info.RequestInfo, options psrpc.ClientOpts, opts ...psrpc
opt(o)
}

if o.SelectionOpts.Jitter < 0 {
o.SelectionOpts.Jitter = 0
}
if o.SelectionOpts.Jitter > 1 {
o.SelectionOpts.Jitter = 1
}

return *o
}

Expand Down
44 changes: 31 additions & 13 deletions pkg/client/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package client
import (
"context"
"errors"
r "math/rand"
"sort"
"time"

"google.golang.org/protobuf/proto"
Expand Down Expand Up @@ -176,36 +178,52 @@ func selectServer(
time.AfterFunc(opts.AffinityTimeout, cancel)
}

serverID := ""
best := float32(0)
shorted := false
claims := 0
var resErr error
var claims []*internal.ClaimRequest
var resCount int

for {
select {
case <-ctx.Done():
if best > 0 {
return serverID, nil
if len(claims) > 0 {
sort.Slice(claims, func(i, j int) bool {
return claims[i].Affinity > claims[j].Affinity
})

best := claims[0].Affinity
minAffinity := best * (1 - opts.Jitter)

i := 0
for ; i < len(claims); i++ {
if claims[i].Affinity < minAffinity {
break
}
}

return claims[r.Intn(i)].ServerId, nil
}

if resErr != nil {
return "", resErr
}
if claims == 0 {
return "", psrpc.ErrNoResponse

if len(claims) == 0 {
if resCount > 0 {
return "", psrpc.NewErrorf(psrpc.Unavailable, "no servers available (received %d responses)", resCount)
} else {
return "", psrpc.ErrNoResponse
}
}
return "", psrpc.NewErrorf(psrpc.Unavailable, "no servers available (received %d responses)", claims)

case claim := <-claimChan:
claims++
if (opts.MinimumAffinity > 0 && claim.Affinity >= opts.MinimumAffinity && claim.Affinity > best) ||
(opts.MinimumAffinity <= 0 && claim.Affinity > best) {
resCount++
if (opts.MinimumAffinity > 0 && claim.Affinity >= opts.MinimumAffinity) || opts.MinimumAffinity <= 0 {
if opts.AcceptFirstAvailable || opts.MaximumAffinity > 0 && claim.Affinity >= opts.MaximumAffinity {
return claim.ServerId, nil
}

serverID = claim.ServerId
best = claim.Affinity
claims = append(claims, claim)

if opts.ShortCircuitTimeout > 0 && !shorted {
shorted = true
Expand Down
1 change: 1 addition & 0 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type RequestOpts struct {
type SelectionOpts struct {
MinimumAffinity float32 // minimum affinity for a server to be considered a valid handler
MaximumAffinity float32 // if > 0, any server returning a max score will be selected immediately
Jitter float32 // randomness applied to selection (0 to 1)
AcceptFirstAvailable bool // go fast
AffinityTimeout time.Duration // server selection deadline
ShortCircuitTimeout time.Duration // deadline imposed after receiving first response
Expand Down

0 comments on commit 473b29c

Please sign in to comment.