balancer_conn_wrappers.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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 grpc
  19. import (
  20. "fmt"
  21. "sync"
  22. "google.golang.org/grpc/balancer"
  23. "google.golang.org/grpc/connectivity"
  24. "google.golang.org/grpc/grpclog"
  25. "google.golang.org/grpc/resolver"
  26. )
  27. // scStateUpdate contains the subConn and the new state it changed to.
  28. type scStateUpdate struct {
  29. sc balancer.SubConn
  30. state connectivity.State
  31. }
  32. // scStateUpdateBuffer is an unbounded channel for scStateChangeTuple.
  33. // TODO make a general purpose buffer that uses interface{}.
  34. type scStateUpdateBuffer struct {
  35. c chan *scStateUpdate
  36. mu sync.Mutex
  37. backlog []*scStateUpdate
  38. }
  39. func newSCStateUpdateBuffer() *scStateUpdateBuffer {
  40. return &scStateUpdateBuffer{
  41. c: make(chan *scStateUpdate, 1),
  42. }
  43. }
  44. func (b *scStateUpdateBuffer) put(t *scStateUpdate) {
  45. b.mu.Lock()
  46. defer b.mu.Unlock()
  47. if len(b.backlog) == 0 {
  48. select {
  49. case b.c <- t:
  50. return
  51. default:
  52. }
  53. }
  54. b.backlog = append(b.backlog, t)
  55. }
  56. func (b *scStateUpdateBuffer) load() {
  57. b.mu.Lock()
  58. defer b.mu.Unlock()
  59. if len(b.backlog) > 0 {
  60. select {
  61. case b.c <- b.backlog[0]:
  62. b.backlog[0] = nil
  63. b.backlog = b.backlog[1:]
  64. default:
  65. }
  66. }
  67. }
  68. // get returns the channel that the scStateUpdate will be sent to.
  69. //
  70. // Upon receiving, the caller should call load to send another
  71. // scStateChangeTuple onto the channel if there is any.
  72. func (b *scStateUpdateBuffer) get() <-chan *scStateUpdate {
  73. return b.c
  74. }
  75. // ccBalancerWrapper is a wrapper on top of cc for balancers.
  76. // It implements balancer.ClientConn interface.
  77. type ccBalancerWrapper struct {
  78. cc *ClientConn
  79. balancer balancer.Balancer
  80. stateChangeQueue *scStateUpdateBuffer
  81. ccUpdateCh chan *balancer.ClientConnState
  82. done chan struct{}
  83. mu sync.Mutex
  84. subConns map[*acBalancerWrapper]struct{}
  85. }
  86. func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.BuildOptions) *ccBalancerWrapper {
  87. ccb := &ccBalancerWrapper{
  88. cc: cc,
  89. stateChangeQueue: newSCStateUpdateBuffer(),
  90. ccUpdateCh: make(chan *balancer.ClientConnState, 1),
  91. done: make(chan struct{}),
  92. subConns: make(map[*acBalancerWrapper]struct{}),
  93. }
  94. go ccb.watcher()
  95. ccb.balancer = b.Build(ccb, bopts)
  96. return ccb
  97. }
  98. // watcher balancer functions sequentially, so the balancer can be implemented
  99. // lock-free.
  100. func (ccb *ccBalancerWrapper) watcher() {
  101. for {
  102. select {
  103. case t := <-ccb.stateChangeQueue.get():
  104. ccb.stateChangeQueue.load()
  105. select {
  106. case <-ccb.done:
  107. ccb.balancer.Close()
  108. return
  109. default:
  110. }
  111. if ub, ok := ccb.balancer.(balancer.V2Balancer); ok {
  112. ub.UpdateSubConnState(t.sc, balancer.SubConnState{ConnectivityState: t.state})
  113. } else {
  114. ccb.balancer.HandleSubConnStateChange(t.sc, t.state)
  115. }
  116. case s := <-ccb.ccUpdateCh:
  117. select {
  118. case <-ccb.done:
  119. ccb.balancer.Close()
  120. return
  121. default:
  122. }
  123. if ub, ok := ccb.balancer.(balancer.V2Balancer); ok {
  124. ub.UpdateClientConnState(*s)
  125. } else {
  126. ccb.balancer.HandleResolvedAddrs(s.ResolverState.Addresses, nil)
  127. }
  128. case <-ccb.done:
  129. }
  130. select {
  131. case <-ccb.done:
  132. ccb.balancer.Close()
  133. ccb.mu.Lock()
  134. scs := ccb.subConns
  135. ccb.subConns = nil
  136. ccb.mu.Unlock()
  137. for acbw := range scs {
  138. ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
  139. }
  140. ccb.UpdateBalancerState(connectivity.Connecting, nil)
  141. return
  142. default:
  143. }
  144. ccb.cc.firstResolveEvent.Fire()
  145. }
  146. }
  147. func (ccb *ccBalancerWrapper) close() {
  148. close(ccb.done)
  149. }
  150. func (ccb *ccBalancerWrapper) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
  151. // When updating addresses for a SubConn, if the address in use is not in
  152. // the new addresses, the old ac will be tearDown() and a new ac will be
  153. // created. tearDown() generates a state change with Shutdown state, we
  154. // don't want the balancer to receive this state change. So before
  155. // tearDown() on the old ac, ac.acbw (acWrapper) will be set to nil, and
  156. // this function will be called with (nil, Shutdown). We don't need to call
  157. // balancer method in this case.
  158. if sc == nil {
  159. return
  160. }
  161. ccb.stateChangeQueue.put(&scStateUpdate{
  162. sc: sc,
  163. state: s,
  164. })
  165. }
  166. func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) {
  167. if ccb.cc.curBalancerName != grpclbName {
  168. // Filter any grpclb addresses since we don't have the grpclb balancer.
  169. s := &ccs.ResolverState
  170. for i := 0; i < len(s.Addresses); {
  171. if s.Addresses[i].Type == resolver.GRPCLB {
  172. copy(s.Addresses[i:], s.Addresses[i+1:])
  173. s.Addresses = s.Addresses[:len(s.Addresses)-1]
  174. continue
  175. }
  176. i++
  177. }
  178. }
  179. select {
  180. case <-ccb.ccUpdateCh:
  181. default:
  182. }
  183. ccb.ccUpdateCh <- ccs
  184. }
  185. func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
  186. if len(addrs) <= 0 {
  187. return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
  188. }
  189. ccb.mu.Lock()
  190. defer ccb.mu.Unlock()
  191. if ccb.subConns == nil {
  192. return nil, fmt.Errorf("grpc: ClientConn balancer wrapper was closed")
  193. }
  194. ac, err := ccb.cc.newAddrConn(addrs, opts)
  195. if err != nil {
  196. return nil, err
  197. }
  198. acbw := &acBalancerWrapper{ac: ac}
  199. acbw.ac.mu.Lock()
  200. ac.acbw = acbw
  201. acbw.ac.mu.Unlock()
  202. ccb.subConns[acbw] = struct{}{}
  203. return acbw, nil
  204. }
  205. func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
  206. acbw, ok := sc.(*acBalancerWrapper)
  207. if !ok {
  208. return
  209. }
  210. ccb.mu.Lock()
  211. defer ccb.mu.Unlock()
  212. if ccb.subConns == nil {
  213. return
  214. }
  215. delete(ccb.subConns, acbw)
  216. ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
  217. }
  218. func (ccb *ccBalancerWrapper) UpdateBalancerState(s connectivity.State, p balancer.Picker) {
  219. ccb.mu.Lock()
  220. defer ccb.mu.Unlock()
  221. if ccb.subConns == nil {
  222. return
  223. }
  224. // Update picker before updating state. Even though the ordering here does
  225. // not matter, it can lead to multiple calls of Pick in the common start-up
  226. // case where we wait for ready and then perform an RPC. If the picker is
  227. // updated later, we could call the "connecting" picker when the state is
  228. // updated, and then call the "ready" picker after the picker gets updated.
  229. ccb.cc.blockingpicker.updatePicker(p)
  230. ccb.cc.csMgr.updateState(s)
  231. }
  232. func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOption) {
  233. ccb.cc.resolveNow(o)
  234. }
  235. func (ccb *ccBalancerWrapper) Target() string {
  236. return ccb.cc.target
  237. }
  238. // acBalancerWrapper is a wrapper on top of ac for balancers.
  239. // It implements balancer.SubConn interface.
  240. type acBalancerWrapper struct {
  241. mu sync.Mutex
  242. ac *addrConn
  243. }
  244. func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
  245. acbw.mu.Lock()
  246. defer acbw.mu.Unlock()
  247. if len(addrs) <= 0 {
  248. acbw.ac.tearDown(errConnDrain)
  249. return
  250. }
  251. if !acbw.ac.tryUpdateAddrs(addrs) {
  252. cc := acbw.ac.cc
  253. opts := acbw.ac.scopts
  254. acbw.ac.mu.Lock()
  255. // Set old ac.acbw to nil so the Shutdown state update will be ignored
  256. // by balancer.
  257. //
  258. // TODO(bar) the state transition could be wrong when tearDown() old ac
  259. // and creating new ac, fix the transition.
  260. acbw.ac.acbw = nil
  261. acbw.ac.mu.Unlock()
  262. acState := acbw.ac.getState()
  263. acbw.ac.tearDown(errConnDrain)
  264. if acState == connectivity.Shutdown {
  265. return
  266. }
  267. ac, err := cc.newAddrConn(addrs, opts)
  268. if err != nil {
  269. grpclog.Warningf("acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err)
  270. return
  271. }
  272. acbw.ac = ac
  273. ac.mu.Lock()
  274. ac.acbw = acbw
  275. ac.mu.Unlock()
  276. if acState != connectivity.Idle {
  277. ac.connect()
  278. }
  279. }
  280. }
  281. func (acbw *acBalancerWrapper) Connect() {
  282. acbw.mu.Lock()
  283. defer acbw.mu.Unlock()
  284. acbw.ac.connect()
  285. }
  286. func (acbw *acBalancerWrapper) getAddrConn() *addrConn {
  287. acbw.mu.Lock()
  288. defer acbw.mu.Unlock()
  289. return acbw.ac
  290. }