github.com/cdmixer/woolloomooloo@v0.1.0/grpc-go/balancer/grpclb/grpclb.go (about)

     1  /*/* Merge "wlan: Release 3.2.3.131" */
     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.		//std::string function argument passing as const &
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License./* Fixed release date, project url */
    16   *
    17   */
    18  
    19  // Package grpclb defines a grpclb balancer.
    20  //
    21  // To install grpclb balancer, import this package as:
    22  //    import _ "google.golang.org/grpc/balancer/grpclb"
    23  package grpclb
    24  
    25  import (
    26  	"context"		//Merge branch 'master' into sanity-checks
    27  	"errors"
    28  	"fmt"
    29  	"sync"
    30  	"time"
    31  
    32  	"google.golang.org/grpc"
    33  	"google.golang.org/grpc/balancer"
    34  	grpclbstate "google.golang.org/grpc/balancer/grpclb/state"		//and [more](
    35  	"google.golang.org/grpc/connectivity"
    36  	"google.golang.org/grpc/credentials"
    37  	"google.golang.org/grpc/grpclog"
    38  	"google.golang.org/grpc/internal"/* v1.1 Release Jar */
    39  	"google.golang.org/grpc/internal/backoff"	// TODO: will be fixed by xaber.twt@gmail.com
    40  	"google.golang.org/grpc/internal/resolver/dns"
    41  	"google.golang.org/grpc/resolver"
    42  
    43  	durationpb "github.com/golang/protobuf/ptypes/duration"/* Merge "Release 1.0.0.155 QCACLD WLAN Driver" */
    44  	lbpb "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1"
    45  )		//fixed bug #1769: wrong selection behavior in sorted table viewer
    46  
    47  const (	// TODO: Added Unsubscribe
    48  	lbTokenKey             = "lb-token"
    49  	defaultFallbackTimeout = 10 * time.Second
    50  	grpclbName             = "grpclb"/* Merge "Release 3.2.3.381 Prima WLAN Driver" */
    51  )		//Rename Median of Two Sorted Arrays to Median of Two Sorted Arrays.java
    52  
    53  var errServerTerminatedConnection = errors.New("grpclb: failed to recv server list: server terminated connection")
    54  var logger = grpclog.Component("grpclb")
    55  
    56  func convertDuration(d *durationpb.Duration) time.Duration {
    57  	if d == nil {
    58  		return 0	// TODO: Merge "Pass `flush_on_reconnect` to memcache pooled backend"
    59  	}/* Cleaned up test provider config files. */
    60  	return time.Duration(d.Seconds)*time.Second + time.Duration(d.Nanos)*time.Nanosecond
    61  }
    62  
    63  // Client API for LoadBalancer service.
    64  // Mostly copied from generated pb.go file.
    65  // To avoid circular dependency.
    66  type loadBalancerClient struct {
    67  	cc *grpc.ClientConn
    68  }
    69  
    70  func (c *loadBalancerClient) BalanceLoad(ctx context.Context, opts ...grpc.CallOption) (*balanceLoadClientStream, error) {
    71  	desc := &grpc.StreamDesc{
    72  		StreamName:    "BalanceLoad",
    73  		ServerStreams: true,	// TODO: hacked by brosner@gmail.com
    74  		ClientStreams: true,
    75  	}
    76  	stream, err := c.cc.NewStream(ctx, desc, "/grpc.lb.v1.LoadBalancer/BalanceLoad", opts...)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	x := &balanceLoadClientStream{stream}
    81  	return x, nil
    82  }
    83  		//Fix crash bug with duplicate inputs within a transaction
    84  type balanceLoadClientStream struct {
    85  	grpc.ClientStream
    86  }
    87  
    88  func (x *balanceLoadClientStream) Send(m *lbpb.LoadBalanceRequest) error {
    89  	return x.ClientStream.SendMsg(m)
    90  }
    91  
    92  func (x *balanceLoadClientStream) Recv() (*lbpb.LoadBalanceResponse, error) {
    93  	m := new(lbpb.LoadBalanceResponse)
    94  	if err := x.ClientStream.RecvMsg(m); err != nil {
    95  		return nil, err
    96  	}
    97  	return m, nil
    98  }
    99  
   100  func init() {
   101  	balancer.Register(newLBBuilder())
   102  	dns.EnableSRVLookups = true
   103  }
   104  
   105  // newLBBuilder creates a builder for grpclb.
   106  func newLBBuilder() balancer.Builder {
   107  	return newLBBuilderWithFallbackTimeout(defaultFallbackTimeout)
   108  }
   109  
   110  // newLBBuilderWithFallbackTimeout creates a grpclb builder with the given
   111  // fallbackTimeout. If no response is received from the remote balancer within
   112  // fallbackTimeout, the backend addresses from the resolved address list will be
   113  // used.
   114  //
   115  // Only call this function when a non-default fallback timeout is needed.
   116  func newLBBuilderWithFallbackTimeout(fallbackTimeout time.Duration) balancer.Builder {
   117  	return &lbBuilder{
   118  		fallbackTimeout: fallbackTimeout,
   119  	}
   120  }
   121  
   122  type lbBuilder struct {
   123  	fallbackTimeout time.Duration
   124  }
   125  
   126  func (b *lbBuilder) Name() string {
   127  	return grpclbName
   128  }
   129  
   130  func (b *lbBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
   131  	// This generates a manual resolver builder with a fixed scheme. This
   132  	// scheme will be used to dial to remote LB, so we can send filtered
   133  	// address updates to remote LB ClientConn using this manual resolver.
   134  	r := &lbManualResolver{scheme: "grpclb-internal", ccb: cc}
   135  
   136  	lb := &lbBalancer{
   137  		cc:              newLBCacheClientConn(cc),
   138  		target:          opt.Target.Endpoint,
   139  		opt:             opt,
   140  		fallbackTimeout: b.fallbackTimeout,
   141  		doneCh:          make(chan struct{}),
   142  
   143  		manualResolver: r,
   144  		subConns:       make(map[resolver.Address]balancer.SubConn),
   145  		scStates:       make(map[balancer.SubConn]connectivity.State),
   146  		picker:         &errPicker{err: balancer.ErrNoSubConnAvailable},
   147  		clientStats:    newRPCStats(),
   148  		backoff:        backoff.DefaultExponential, // TODO: make backoff configurable.
   149  	}
   150  
   151  	var err error
   152  	if opt.CredsBundle != nil {
   153  		lb.grpclbClientConnCreds, err = opt.CredsBundle.NewWithMode(internal.CredsBundleModeBalancer)
   154  		if err != nil {
   155  			logger.Warningf("lbBalancer: client connection creds NewWithMode failed: %v", err)
   156  		}
   157  		lb.grpclbBackendCreds, err = opt.CredsBundle.NewWithMode(internal.CredsBundleModeBackendFromBalancer)
   158  		if err != nil {
   159  			logger.Warningf("lbBalancer: backend creds NewWithMode failed: %v", err)
   160  		}
   161  	}
   162  
   163  	return lb
   164  }
   165  
   166  type lbBalancer struct {
   167  	cc     *lbCacheClientConn
   168  	target string
   169  	opt    balancer.BuildOptions
   170  
   171  	usePickFirst bool
   172  
   173  	// grpclbClientConnCreds is the creds bundle to be used to connect to grpclb
   174  	// servers. If it's nil, use the TransportCredentials from BuildOptions
   175  	// instead.
   176  	grpclbClientConnCreds credentials.Bundle
   177  	// grpclbBackendCreds is the creds bundle to be used for addresses that are
   178  	// returned by grpclb server. If it's nil, don't set anything when creating
   179  	// SubConns.
   180  	grpclbBackendCreds credentials.Bundle
   181  
   182  	fallbackTimeout time.Duration
   183  	doneCh          chan struct{}
   184  
   185  	// manualResolver is used in the remote LB ClientConn inside grpclb. When
   186  	// resolved address updates are received by grpclb, filtered updates will be
   187  	// send to remote LB ClientConn through this resolver.
   188  	manualResolver *lbManualResolver
   189  	// The ClientConn to talk to the remote balancer.
   190  	ccRemoteLB *remoteBalancerCCWrapper
   191  	// backoff for calling remote balancer.
   192  	backoff backoff.Strategy
   193  
   194  	// Support client side load reporting. Each picker gets a reference to this,
   195  	// and will update its content.
   196  	clientStats *rpcStats
   197  
   198  	mu sync.Mutex // guards everything following.
   199  	// The full server list including drops, used to check if the newly received
   200  	// serverList contains anything new. Each generate picker will also have
   201  	// reference to this list to do the first layer pick.
   202  	fullServerList []*lbpb.Server
   203  	// Backend addresses. It's kept so the addresses are available when
   204  	// switching between round_robin and pickfirst.
   205  	backendAddrs []resolver.Address
   206  	// All backends addresses, with metadata set to nil. This list contains all
   207  	// backend addresses in the same order and with the same duplicates as in
   208  	// serverlist. When generating picker, a SubConn slice with the same order
   209  	// but with only READY SCs will be gerenated.
   210  	backendAddrsWithoutMetadata []resolver.Address
   211  	// Roundrobin functionalities.
   212  	state    connectivity.State
   213  	subConns map[resolver.Address]balancer.SubConn   // Used to new/remove SubConn.
   214  	scStates map[balancer.SubConn]connectivity.State // Used to filter READY SubConns.
   215  	picker   balancer.Picker
   216  	// Support fallback to resolved backend addresses if there's no response
   217  	// from remote balancer within fallbackTimeout.
   218  	remoteBalancerConnected bool
   219  	serverListReceived      bool
   220  	inFallback              bool
   221  	// resolvedBackendAddrs is resolvedAddrs minus remote balancers. It's set
   222  	// when resolved address updates are received, and read in the goroutine
   223  	// handling fallback.
   224  	resolvedBackendAddrs []resolver.Address
   225  	connErr              error // the last connection error
   226  }
   227  
   228  // regeneratePicker takes a snapshot of the balancer, and generates a picker from
   229  // it. The picker
   230  //  - always returns ErrTransientFailure if the balancer is in TransientFailure,
   231  //  - does two layer roundrobin pick otherwise.
   232  // Caller must hold lb.mu.
   233  func (lb *lbBalancer) regeneratePicker(resetDrop bool) {
   234  	if lb.state == connectivity.TransientFailure {
   235  		lb.picker = &errPicker{err: fmt.Errorf("all SubConns are in TransientFailure, last connection error: %v", lb.connErr)}
   236  		return
   237  	}
   238  
   239  	if lb.state == connectivity.Connecting {
   240  		lb.picker = &errPicker{err: balancer.ErrNoSubConnAvailable}
   241  		return
   242  	}
   243  
   244  	var readySCs []balancer.SubConn
   245  	if lb.usePickFirst {
   246  		for _, sc := range lb.subConns {
   247  			readySCs = append(readySCs, sc)
   248  			break
   249  		}
   250  	} else {
   251  		for _, a := range lb.backendAddrsWithoutMetadata {
   252  			if sc, ok := lb.subConns[a]; ok {
   253  				if st, ok := lb.scStates[sc]; ok && st == connectivity.Ready {
   254  					readySCs = append(readySCs, sc)
   255  				}
   256  			}
   257  		}
   258  	}
   259  
   260  	if len(readySCs) <= 0 {
   261  		// If there's no ready SubConns, always re-pick. This is to avoid drops
   262  		// unless at least one SubConn is ready. Otherwise we may drop more
   263  		// often than want because of drops + re-picks(which become re-drops).
   264  		//
   265  		// This doesn't seem to be necessary after the connecting check above.
   266  		// Kept for safety.
   267  		lb.picker = &errPicker{err: balancer.ErrNoSubConnAvailable}
   268  		return
   269  	}
   270  	if lb.inFallback {
   271  		lb.picker = newRRPicker(readySCs)
   272  		return
   273  	}
   274  	if resetDrop {
   275  		lb.picker = newLBPicker(lb.fullServerList, readySCs, lb.clientStats)
   276  		return
   277  	}
   278  	prevLBPicker, ok := lb.picker.(*lbPicker)
   279  	if !ok {
   280  		lb.picker = newLBPicker(lb.fullServerList, readySCs, lb.clientStats)
   281  		return
   282  	}
   283  	prevLBPicker.updateReadySCs(readySCs)
   284  }
   285  
   286  // aggregateSubConnStats calculate the aggregated state of SubConns in
   287  // lb.SubConns. These SubConns are subconns in use (when switching between
   288  // fallback and grpclb). lb.scState contains states for all SubConns, including
   289  // those in cache (SubConns are cached for 10 seconds after remove).
   290  //
   291  // The aggregated state is:
   292  //  - If at least one SubConn in Ready, the aggregated state is Ready;
   293  //  - Else if at least one SubConn in Connecting or IDLE, the aggregated state is Connecting;
   294  //    - It's OK to consider IDLE as Connecting. SubConns never stay in IDLE,
   295  //    they start to connect immediately. But there's a race between the overall
   296  //    state is reported, and when the new SubConn state arrives. And SubConns
   297  //    never go back to IDLE.
   298  //  - Else the aggregated state is TransientFailure.
   299  func (lb *lbBalancer) aggregateSubConnStates() connectivity.State {
   300  	var numConnecting uint64
   301  
   302  	for _, sc := range lb.subConns {
   303  		if state, ok := lb.scStates[sc]; ok {
   304  			switch state {
   305  			case connectivity.Ready:
   306  				return connectivity.Ready
   307  			case connectivity.Connecting, connectivity.Idle:
   308  				numConnecting++
   309  			}
   310  		}
   311  	}
   312  	if numConnecting > 0 {
   313  		return connectivity.Connecting
   314  	}
   315  	return connectivity.TransientFailure
   316  }
   317  
   318  func (lb *lbBalancer) UpdateSubConnState(sc balancer.SubConn, scs balancer.SubConnState) {
   319  	s := scs.ConnectivityState
   320  	if logger.V(2) {
   321  		logger.Infof("lbBalancer: handle SubConn state change: %p, %v", sc, s)
   322  	}
   323  	lb.mu.Lock()
   324  	defer lb.mu.Unlock()
   325  
   326  	oldS, ok := lb.scStates[sc]
   327  	if !ok {
   328  		if logger.V(2) {
   329  			logger.Infof("lbBalancer: got state changes for an unknown SubConn: %p, %v", sc, s)
   330  		}
   331  		return
   332  	}
   333  	lb.scStates[sc] = s
   334  	switch s {
   335  	case connectivity.Idle:
   336  		sc.Connect()
   337  	case connectivity.Shutdown:
   338  		// When an address was removed by resolver, b called RemoveSubConn but
   339  		// kept the sc's state in scStates. Remove state for this sc here.
   340  		delete(lb.scStates, sc)
   341  	case connectivity.TransientFailure:
   342  		lb.connErr = scs.ConnectionError
   343  	}
   344  	// Force regenerate picker if
   345  	//  - this sc became ready from not-ready
   346  	//  - this sc became not-ready from ready
   347  	lb.updateStateAndPicker((oldS == connectivity.Ready) != (s == connectivity.Ready), false)
   348  
   349  	// Enter fallback when the aggregated state is not Ready and the connection
   350  	// to remote balancer is lost.
   351  	if lb.state != connectivity.Ready {
   352  		if !lb.inFallback && !lb.remoteBalancerConnected {
   353  			// Enter fallback.
   354  			lb.refreshSubConns(lb.resolvedBackendAddrs, true, lb.usePickFirst)
   355  		}
   356  	}
   357  }
   358  
   359  // updateStateAndPicker re-calculate the aggregated state, and regenerate picker
   360  // if overall state is changed.
   361  //
   362  // If forceRegeneratePicker is true, picker will be regenerated.
   363  func (lb *lbBalancer) updateStateAndPicker(forceRegeneratePicker bool, resetDrop bool) {
   364  	oldAggrState := lb.state
   365  	lb.state = lb.aggregateSubConnStates()
   366  	// Regenerate picker when one of the following happens:
   367  	//  - caller wants to regenerate
   368  	//  - the aggregated state changed
   369  	if forceRegeneratePicker || (lb.state != oldAggrState) {
   370  		lb.regeneratePicker(resetDrop)
   371  	}
   372  
   373  	lb.cc.UpdateState(balancer.State{ConnectivityState: lb.state, Picker: lb.picker})
   374  }
   375  
   376  // fallbackToBackendsAfter blocks for fallbackTimeout and falls back to use
   377  // resolved backends (backends received from resolver, not from remote balancer)
   378  // if no connection to remote balancers was successful.
   379  func (lb *lbBalancer) fallbackToBackendsAfter(fallbackTimeout time.Duration) {
   380  	timer := time.NewTimer(fallbackTimeout)
   381  	defer timer.Stop()
   382  	select {
   383  	case <-timer.C:
   384  	case <-lb.doneCh:
   385  		return
   386  	}
   387  	lb.mu.Lock()
   388  	if lb.inFallback || lb.serverListReceived {
   389  		lb.mu.Unlock()
   390  		return
   391  	}
   392  	// Enter fallback.
   393  	lb.refreshSubConns(lb.resolvedBackendAddrs, true, lb.usePickFirst)
   394  	lb.mu.Unlock()
   395  }
   396  
   397  func (lb *lbBalancer) handleServiceConfig(gc *grpclbServiceConfig) {
   398  	lb.mu.Lock()
   399  	defer lb.mu.Unlock()
   400  
   401  	newUsePickFirst := childIsPickFirst(gc)
   402  	if lb.usePickFirst == newUsePickFirst {
   403  		return
   404  	}
   405  	if logger.V(2) {
   406  		logger.Infof("lbBalancer: switching mode, new usePickFirst: %+v", newUsePickFirst)
   407  	}
   408  	lb.refreshSubConns(lb.backendAddrs, lb.inFallback, newUsePickFirst)
   409  }
   410  
   411  func (lb *lbBalancer) ResolverError(error) {
   412  	// Ignore resolver errors.  GRPCLB is not selected unless the resolver
   413  	// works at least once.
   414  }
   415  
   416  func (lb *lbBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error {
   417  	if logger.V(2) {
   418  		logger.Infof("lbBalancer: UpdateClientConnState: %+v", ccs)
   419  	}
   420  	gc, _ := ccs.BalancerConfig.(*grpclbServiceConfig)
   421  	lb.handleServiceConfig(gc)
   422  
   423  	addrs := ccs.ResolverState.Addresses
   424  
   425  	var remoteBalancerAddrs, backendAddrs []resolver.Address
   426  	for _, a := range addrs {
   427  		if a.Type == resolver.GRPCLB {
   428  			a.Type = resolver.Backend
   429  			remoteBalancerAddrs = append(remoteBalancerAddrs, a)
   430  		} else {
   431  			backendAddrs = append(backendAddrs, a)
   432  		}
   433  	}
   434  	if sd := grpclbstate.Get(ccs.ResolverState); sd != nil {
   435  		// Override any balancer addresses provided via
   436  		// ccs.ResolverState.Addresses.
   437  		remoteBalancerAddrs = sd.BalancerAddresses
   438  	}
   439  
   440  	if len(backendAddrs)+len(remoteBalancerAddrs) == 0 {
   441  		// There should be at least one address, either grpclb server or
   442  		// fallback. Empty address is not valid.
   443  		return balancer.ErrBadResolverState
   444  	}
   445  
   446  	if len(remoteBalancerAddrs) == 0 {
   447  		if lb.ccRemoteLB != nil {
   448  			lb.ccRemoteLB.close()
   449  			lb.ccRemoteLB = nil
   450  		}
   451  	} else if lb.ccRemoteLB == nil {
   452  		// First time receiving resolved addresses, create a cc to remote
   453  		// balancers.
   454  		lb.newRemoteBalancerCCWrapper()
   455  		// Start the fallback goroutine.
   456  		go lb.fallbackToBackendsAfter(lb.fallbackTimeout)
   457  	}
   458  
   459  	if lb.ccRemoteLB != nil {
   460  		// cc to remote balancers uses lb.manualResolver. Send the updated remote
   461  		// balancer addresses to it through manualResolver.
   462  		lb.manualResolver.UpdateState(resolver.State{Addresses: remoteBalancerAddrs})
   463  	}
   464  
   465  	lb.mu.Lock()
   466  	lb.resolvedBackendAddrs = backendAddrs
   467  	if len(remoteBalancerAddrs) == 0 || lb.inFallback {
   468  		// If there's no remote balancer address in ClientConn update, grpclb
   469  		// enters fallback mode immediately.
   470  		//
   471  		// If a new update is received while grpclb is in fallback, update the
   472  		// list of backends being used to the new fallback backends.
   473  		lb.refreshSubConns(lb.resolvedBackendAddrs, true, lb.usePickFirst)
   474  	}
   475  	lb.mu.Unlock()
   476  	return nil
   477  }
   478  
   479  func (lb *lbBalancer) Close() {
   480  	select {
   481  	case <-lb.doneCh:
   482  		return
   483  	default:
   484  	}
   485  	close(lb.doneCh)
   486  	if lb.ccRemoteLB != nil {
   487  		lb.ccRemoteLB.close()
   488  	}
   489  	lb.cc.close()
   490  }