balancer.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*
  2. *
  3. * Copyright 2016 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. "net"
  22. "sync"
  23. "golang.org/x/net/context"
  24. "google.golang.org/grpc/codes"
  25. "google.golang.org/grpc/credentials"
  26. "google.golang.org/grpc/grpclog"
  27. "google.golang.org/grpc/naming"
  28. "google.golang.org/grpc/status"
  29. )
  30. // Address represents a server the client connects to.
  31. //
  32. // Deprecated: please use package balancer.
  33. type Address struct {
  34. // Addr is the server address on which a connection will be established.
  35. Addr string
  36. // Metadata is the information associated with Addr, which may be used
  37. // to make load balancing decision.
  38. Metadata interface{}
  39. }
  40. // BalancerConfig specifies the configurations for Balancer.
  41. //
  42. // Deprecated: please use package balancer.
  43. type BalancerConfig struct {
  44. // DialCreds is the transport credential the Balancer implementation can
  45. // use to dial to a remote load balancer server. The Balancer implementations
  46. // can ignore this if it does not need to talk to another party securely.
  47. DialCreds credentials.TransportCredentials
  48. // Dialer is the custom dialer the Balancer implementation can use to dial
  49. // to a remote load balancer server. The Balancer implementations
  50. // can ignore this if it doesn't need to talk to remote balancer.
  51. Dialer func(context.Context, string) (net.Conn, error)
  52. }
  53. // BalancerGetOptions configures a Get call.
  54. //
  55. // Deprecated: please use package balancer.
  56. type BalancerGetOptions struct {
  57. // BlockingWait specifies whether Get should block when there is no
  58. // connected address.
  59. BlockingWait bool
  60. }
  61. // Balancer chooses network addresses for RPCs.
  62. //
  63. // Deprecated: please use package balancer.
  64. type Balancer interface {
  65. // Start does the initialization work to bootstrap a Balancer. For example,
  66. // this function may start the name resolution and watch the updates. It will
  67. // be called when dialing.
  68. Start(target string, config BalancerConfig) error
  69. // Up informs the Balancer that gRPC has a connection to the server at
  70. // addr. It returns down which is called once the connection to addr gets
  71. // lost or closed.
  72. // TODO: It is not clear how to construct and take advantage of the meaningful error
  73. // parameter for down. Need realistic demands to guide.
  74. Up(addr Address) (down func(error))
  75. // Get gets the address of a server for the RPC corresponding to ctx.
  76. // i) If it returns a connected address, gRPC internals issues the RPC on the
  77. // connection to this address;
  78. // ii) If it returns an address on which the connection is under construction
  79. // (initiated by Notify(...)) but not connected, gRPC internals
  80. // * fails RPC if the RPC is fail-fast and connection is in the TransientFailure or
  81. // Shutdown state;
  82. // or
  83. // * issues RPC on the connection otherwise.
  84. // iii) If it returns an address on which the connection does not exist, gRPC
  85. // internals treats it as an error and will fail the corresponding RPC.
  86. //
  87. // Therefore, the following is the recommended rule when writing a custom Balancer.
  88. // If opts.BlockingWait is true, it should return a connected address or
  89. // block if there is no connected address. It should respect the timeout or
  90. // cancellation of ctx when blocking. If opts.BlockingWait is false (for fail-fast
  91. // RPCs), it should return an address it has notified via Notify(...) immediately
  92. // instead of blocking.
  93. //
  94. // The function returns put which is called once the rpc has completed or failed.
  95. // put can collect and report RPC stats to a remote load balancer.
  96. //
  97. // This function should only return the errors Balancer cannot recover by itself.
  98. // gRPC internals will fail the RPC if an error is returned.
  99. Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error)
  100. // Notify returns a channel that is used by gRPC internals to watch the addresses
  101. // gRPC needs to connect. The addresses might be from a name resolver or remote
  102. // load balancer. gRPC internals will compare it with the existing connected
  103. // addresses. If the address Balancer notified is not in the existing connected
  104. // addresses, gRPC starts to connect the address. If an address in the existing
  105. // connected addresses is not in the notification list, the corresponding connection
  106. // is shutdown gracefully. Otherwise, there are no operations to take. Note that
  107. // the Address slice must be the full list of the Addresses which should be connected.
  108. // It is NOT delta.
  109. Notify() <-chan []Address
  110. // Close shuts down the balancer.
  111. Close() error
  112. }
  113. // downErr implements net.Error. It is constructed by gRPC internals and passed to the down
  114. // call of Balancer.
  115. type downErr struct {
  116. timeout bool
  117. temporary bool
  118. desc string
  119. }
  120. func (e downErr) Error() string { return e.desc }
  121. func (e downErr) Timeout() bool { return e.timeout }
  122. func (e downErr) Temporary() bool { return e.temporary }
  123. func downErrorf(timeout, temporary bool, format string, a ...interface{}) downErr {
  124. return downErr{
  125. timeout: timeout,
  126. temporary: temporary,
  127. desc: fmt.Sprintf(format, a...),
  128. }
  129. }
  130. // RoundRobin returns a Balancer that selects addresses round-robin. It uses r to watch
  131. // the name resolution updates and updates the addresses available correspondingly.
  132. //
  133. // Deprecated: please use package balancer/roundrobin.
  134. func RoundRobin(r naming.Resolver) Balancer {
  135. return &roundRobin{r: r}
  136. }
  137. type addrInfo struct {
  138. addr Address
  139. connected bool
  140. }
  141. type roundRobin struct {
  142. r naming.Resolver
  143. w naming.Watcher
  144. addrs []*addrInfo // all the addresses the client should potentially connect
  145. mu sync.Mutex
  146. addrCh chan []Address // the channel to notify gRPC internals the list of addresses the client should connect to.
  147. next int // index of the next address to return for Get()
  148. waitCh chan struct{} // the channel to block when there is no connected address available
  149. done bool // The Balancer is closed.
  150. }
  151. func (rr *roundRobin) watchAddrUpdates() error {
  152. updates, err := rr.w.Next()
  153. if err != nil {
  154. grpclog.Warningf("grpc: the naming watcher stops working due to %v.", err)
  155. return err
  156. }
  157. rr.mu.Lock()
  158. defer rr.mu.Unlock()
  159. for _, update := range updates {
  160. addr := Address{
  161. Addr: update.Addr,
  162. Metadata: update.Metadata,
  163. }
  164. switch update.Op {
  165. case naming.Add:
  166. var exist bool
  167. for _, v := range rr.addrs {
  168. if addr == v.addr {
  169. exist = true
  170. grpclog.Infoln("grpc: The name resolver wanted to add an existing address: ", addr)
  171. break
  172. }
  173. }
  174. if exist {
  175. continue
  176. }
  177. rr.addrs = append(rr.addrs, &addrInfo{addr: addr})
  178. case naming.Delete:
  179. for i, v := range rr.addrs {
  180. if addr == v.addr {
  181. copy(rr.addrs[i:], rr.addrs[i+1:])
  182. rr.addrs = rr.addrs[:len(rr.addrs)-1]
  183. break
  184. }
  185. }
  186. default:
  187. grpclog.Errorln("Unknown update.Op ", update.Op)
  188. }
  189. }
  190. // Make a copy of rr.addrs and write it onto rr.addrCh so that gRPC internals gets notified.
  191. open := make([]Address, len(rr.addrs))
  192. for i, v := range rr.addrs {
  193. open[i] = v.addr
  194. }
  195. if rr.done {
  196. return ErrClientConnClosing
  197. }
  198. select {
  199. case <-rr.addrCh:
  200. default:
  201. }
  202. rr.addrCh <- open
  203. return nil
  204. }
  205. func (rr *roundRobin) Start(target string, config BalancerConfig) error {
  206. rr.mu.Lock()
  207. defer rr.mu.Unlock()
  208. if rr.done {
  209. return ErrClientConnClosing
  210. }
  211. if rr.r == nil {
  212. // If there is no name resolver installed, it is not needed to
  213. // do name resolution. In this case, target is added into rr.addrs
  214. // as the only address available and rr.addrCh stays nil.
  215. rr.addrs = append(rr.addrs, &addrInfo{addr: Address{Addr: target}})
  216. return nil
  217. }
  218. w, err := rr.r.Resolve(target)
  219. if err != nil {
  220. return err
  221. }
  222. rr.w = w
  223. rr.addrCh = make(chan []Address, 1)
  224. go func() {
  225. for {
  226. if err := rr.watchAddrUpdates(); err != nil {
  227. return
  228. }
  229. }
  230. }()
  231. return nil
  232. }
  233. // Up sets the connected state of addr and sends notification if there are pending
  234. // Get() calls.
  235. func (rr *roundRobin) Up(addr Address) func(error) {
  236. rr.mu.Lock()
  237. defer rr.mu.Unlock()
  238. var cnt int
  239. for _, a := range rr.addrs {
  240. if a.addr == addr {
  241. if a.connected {
  242. return nil
  243. }
  244. a.connected = true
  245. }
  246. if a.connected {
  247. cnt++
  248. }
  249. }
  250. // addr is only one which is connected. Notify the Get() callers who are blocking.
  251. if cnt == 1 && rr.waitCh != nil {
  252. close(rr.waitCh)
  253. rr.waitCh = nil
  254. }
  255. return func(err error) {
  256. rr.down(addr, err)
  257. }
  258. }
  259. // down unsets the connected state of addr.
  260. func (rr *roundRobin) down(addr Address, err error) {
  261. rr.mu.Lock()
  262. defer rr.mu.Unlock()
  263. for _, a := range rr.addrs {
  264. if addr == a.addr {
  265. a.connected = false
  266. break
  267. }
  268. }
  269. }
  270. // Get returns the next addr in the rotation.
  271. func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) {
  272. var ch chan struct{}
  273. rr.mu.Lock()
  274. if rr.done {
  275. rr.mu.Unlock()
  276. err = ErrClientConnClosing
  277. return
  278. }
  279. if len(rr.addrs) > 0 {
  280. if rr.next >= len(rr.addrs) {
  281. rr.next = 0
  282. }
  283. next := rr.next
  284. for {
  285. a := rr.addrs[next]
  286. next = (next + 1) % len(rr.addrs)
  287. if a.connected {
  288. addr = a.addr
  289. rr.next = next
  290. rr.mu.Unlock()
  291. return
  292. }
  293. if next == rr.next {
  294. // Has iterated all the possible address but none is connected.
  295. break
  296. }
  297. }
  298. }
  299. if !opts.BlockingWait {
  300. if len(rr.addrs) == 0 {
  301. rr.mu.Unlock()
  302. err = status.Errorf(codes.Unavailable, "there is no address available")
  303. return
  304. }
  305. // Returns the next addr on rr.addrs for failfast RPCs.
  306. addr = rr.addrs[rr.next].addr
  307. rr.next++
  308. rr.mu.Unlock()
  309. return
  310. }
  311. // Wait on rr.waitCh for non-failfast RPCs.
  312. if rr.waitCh == nil {
  313. ch = make(chan struct{})
  314. rr.waitCh = ch
  315. } else {
  316. ch = rr.waitCh
  317. }
  318. rr.mu.Unlock()
  319. for {
  320. select {
  321. case <-ctx.Done():
  322. err = ctx.Err()
  323. return
  324. case <-ch:
  325. rr.mu.Lock()
  326. if rr.done {
  327. rr.mu.Unlock()
  328. err = ErrClientConnClosing
  329. return
  330. }
  331. if len(rr.addrs) > 0 {
  332. if rr.next >= len(rr.addrs) {
  333. rr.next = 0
  334. }
  335. next := rr.next
  336. for {
  337. a := rr.addrs[next]
  338. next = (next + 1) % len(rr.addrs)
  339. if a.connected {
  340. addr = a.addr
  341. rr.next = next
  342. rr.mu.Unlock()
  343. return
  344. }
  345. if next == rr.next {
  346. // Has iterated all the possible address but none is connected.
  347. break
  348. }
  349. }
  350. }
  351. // The newly added addr got removed by Down() again.
  352. if rr.waitCh == nil {
  353. ch = make(chan struct{})
  354. rr.waitCh = ch
  355. } else {
  356. ch = rr.waitCh
  357. }
  358. rr.mu.Unlock()
  359. }
  360. }
  361. }
  362. func (rr *roundRobin) Notify() <-chan []Address {
  363. return rr.addrCh
  364. }
  365. func (rr *roundRobin) Close() error {
  366. rr.mu.Lock()
  367. defer rr.mu.Unlock()
  368. if rr.done {
  369. return errBalancerClosed
  370. }
  371. rr.done = true
  372. if rr.w != nil {
  373. rr.w.Close()
  374. }
  375. if rr.waitCh != nil {
  376. close(rr.waitCh)
  377. rr.waitCh = nil
  378. }
  379. if rr.addrCh != nil {
  380. close(rr.addrCh)
  381. }
  382. return nil
  383. }
  384. // pickFirst is used to test multi-addresses in one addrConn in which all addresses share the same addrConn.
  385. // It is a wrapper around roundRobin balancer. The logic of all methods works fine because balancer.Get()
  386. // returns the only address Up by resetTransport().
  387. type pickFirst struct {
  388. *roundRobin
  389. }
  390. func pickFirstBalancerV1(r naming.Resolver) Balancer {
  391. return &pickFirst{&roundRobin{r: r}}
  392. }