roundrobin.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package roundrobin
  2. import (
  3. "context"
  4. "math/rand"
  5. "sync"
  6. "time"
  7. "google.golang.org/grpc/balancer"
  8. "google.golang.org/grpc/balancer/base"
  9. "google.golang.org/grpc/resolver"
  10. )
  11. const Name = "rr"
  12. func init() {
  13. balancer.Register(newBuilder())
  14. }
  15. type roundRobinPickerBuilder struct{}
  16. func newBuilder() balancer.Builder {
  17. return base.NewBalancerBuilder(Name, new(roundRobinPickerBuilder))
  18. }
  19. func (b *roundRobinPickerBuilder) Build(readySCs map[resolver.Address]balancer.SubConn) balancer.Picker {
  20. if len(readySCs) == 0 {
  21. return base.NewErrPicker(balancer.ErrNoSubConnAvailable)
  22. }
  23. rand.Seed(time.Now().UnixNano())
  24. picker := &roundRobinPicker{
  25. index: rand.Int(),
  26. }
  27. for addr, conn := range readySCs {
  28. picker.conns = append(picker.conns, &subConn{
  29. addr: addr,
  30. conn: conn,
  31. })
  32. }
  33. return picker
  34. }
  35. type roundRobinPicker struct {
  36. conns []*subConn
  37. index int
  38. lock sync.Mutex
  39. }
  40. func (p *roundRobinPicker) Pick(ctx context.Context, info balancer.PickInfo) (
  41. conn balancer.SubConn, done func(balancer.DoneInfo), err error) {
  42. p.lock.Lock()
  43. defer p.lock.Unlock()
  44. p.index = (p.index + 1) % len(p.conns)
  45. return p.conns[p.index].conn, func(info balancer.DoneInfo) {
  46. }, nil
  47. }
  48. type subConn struct {
  49. addr resolver.Address
  50. conn balancer.SubConn
  51. }