balancer.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. *
  3. * Copyright 2017 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package base
  19. import (
  20. "context"
  21. "google.golang.org/grpc/balancer"
  22. "google.golang.org/grpc/connectivity"
  23. "google.golang.org/grpc/grpclog"
  24. "google.golang.org/grpc/resolver"
  25. )
  26. type baseBuilder struct {
  27. name string
  28. pickerBuilder PickerBuilder
  29. config Config
  30. }
  31. func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
  32. return &baseBalancer{
  33. cc: cc,
  34. pickerBuilder: bb.pickerBuilder,
  35. subConns: make(map[resolver.Address]balancer.SubConn),
  36. scStates: make(map[balancer.SubConn]connectivity.State),
  37. csEvltr: &balancer.ConnectivityStateEvaluator{},
  38. // Initialize picker to a picker that always return
  39. // ErrNoSubConnAvailable, because when state of a SubConn changes, we
  40. // may call UpdateBalancerState with this picker.
  41. picker: NewErrPicker(balancer.ErrNoSubConnAvailable),
  42. config: bb.config,
  43. }
  44. }
  45. func (bb *baseBuilder) Name() string {
  46. return bb.name
  47. }
  48. type baseBalancer struct {
  49. cc balancer.ClientConn
  50. pickerBuilder PickerBuilder
  51. csEvltr *balancer.ConnectivityStateEvaluator
  52. state connectivity.State
  53. subConns map[resolver.Address]balancer.SubConn
  54. scStates map[balancer.SubConn]connectivity.State
  55. picker balancer.Picker
  56. config Config
  57. }
  58. func (b *baseBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
  59. panic("not implemented")
  60. }
  61. func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) {
  62. // TODO: handle s.ResolverState.Err (log if not nil) once implemented.
  63. // TODO: handle s.ResolverState.ServiceConfig?
  64. if grpclog.V(2) {
  65. grpclog.Infoln("base.baseBalancer: got new ClientConn state: ", s)
  66. }
  67. // addrsSet is the set converted from addrs, it's used for quick lookup of an address.
  68. addrsSet := make(map[resolver.Address]struct{})
  69. for _, a := range s.ResolverState.Addresses {
  70. addrsSet[a] = struct{}{}
  71. if _, ok := b.subConns[a]; !ok {
  72. // a is a new address (not existing in b.subConns).
  73. sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{HealthCheckEnabled: b.config.HealthCheck})
  74. if err != nil {
  75. grpclog.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
  76. continue
  77. }
  78. b.subConns[a] = sc
  79. b.scStates[sc] = connectivity.Idle
  80. sc.Connect()
  81. }
  82. }
  83. for a, sc := range b.subConns {
  84. // a was removed by resolver.
  85. if _, ok := addrsSet[a]; !ok {
  86. b.cc.RemoveSubConn(sc)
  87. delete(b.subConns, a)
  88. // Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
  89. // The entry will be deleted in HandleSubConnStateChange.
  90. }
  91. }
  92. }
  93. // regeneratePicker takes a snapshot of the balancer, and generates a picker
  94. // from it. The picker is
  95. // - errPicker with ErrTransientFailure if the balancer is in TransientFailure,
  96. // - built by the pickerBuilder with all READY SubConns otherwise.
  97. func (b *baseBalancer) regeneratePicker() {
  98. if b.state == connectivity.TransientFailure {
  99. b.picker = NewErrPicker(balancer.ErrTransientFailure)
  100. return
  101. }
  102. readySCs := make(map[resolver.Address]balancer.SubConn)
  103. // Filter out all ready SCs from full subConn map.
  104. for addr, sc := range b.subConns {
  105. if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
  106. readySCs[addr] = sc
  107. }
  108. }
  109. b.picker = b.pickerBuilder.Build(readySCs)
  110. }
  111. func (b *baseBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
  112. panic("not implemented")
  113. }
  114. func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
  115. s := state.ConnectivityState
  116. if grpclog.V(2) {
  117. grpclog.Infof("base.baseBalancer: handle SubConn state change: %p, %v", sc, s)
  118. }
  119. oldS, ok := b.scStates[sc]
  120. if !ok {
  121. if grpclog.V(2) {
  122. grpclog.Infof("base.baseBalancer: got state changes for an unknown SubConn: %p, %v", sc, s)
  123. }
  124. return
  125. }
  126. b.scStates[sc] = s
  127. switch s {
  128. case connectivity.Idle:
  129. sc.Connect()
  130. case connectivity.Shutdown:
  131. // When an address was removed by resolver, b called RemoveSubConn but
  132. // kept the sc's state in scStates. Remove state for this sc here.
  133. delete(b.scStates, sc)
  134. }
  135. oldAggrState := b.state
  136. b.state = b.csEvltr.RecordTransition(oldS, s)
  137. // Regenerate picker when one of the following happens:
  138. // - this sc became ready from not-ready
  139. // - this sc became not-ready from ready
  140. // - the aggregated state of balancer became TransientFailure from non-TransientFailure
  141. // - the aggregated state of balancer became non-TransientFailure from TransientFailure
  142. if (s == connectivity.Ready) != (oldS == connectivity.Ready) ||
  143. (b.state == connectivity.TransientFailure) != (oldAggrState == connectivity.TransientFailure) {
  144. b.regeneratePicker()
  145. }
  146. b.cc.UpdateBalancerState(b.state, b.picker)
  147. }
  148. // Close is a nop because base balancer doesn't have internal state to clean up,
  149. // and it doesn't need to call RemoveSubConn for the SubConns.
  150. func (b *baseBalancer) Close() {
  151. }
  152. // NewErrPicker returns a picker that always returns err on Pick().
  153. func NewErrPicker(err error) balancer.Picker {
  154. return &errPicker{err: err}
  155. }
  156. type errPicker struct {
  157. err error // Pick() always returns this err.
  158. }
  159. func (p *errPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
  160. return nil, nil, p.err
  161. }