• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.grpclb;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.annotations.VisibleForTesting;
22 import io.grpc.Attributes;
23 import io.grpc.ConnectivityStateInfo;
24 import io.grpc.EquivalentAddressGroup;
25 import io.grpc.InternalLogId;
26 import io.grpc.InternalWithLogId;
27 import io.grpc.LoadBalancer;
28 import io.grpc.Status;
29 import io.grpc.internal.BackoffPolicy;
30 import io.grpc.internal.GrpcAttributes;
31 import io.grpc.internal.ObjectPool;
32 import io.grpc.internal.TimeProvider;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.List;
36 import java.util.concurrent.ScheduledExecutorService;
37 import javax.annotation.Nullable;
38 
39 /**
40  * A {@link LoadBalancer} that uses the GRPCLB protocol.
41  *
42  * <p>Optionally, when requested by the naming system, will delegate the work to a local pick-first
43  * or round-robin balancer.
44  */
45 class GrpclbLoadBalancer extends LoadBalancer implements InternalWithLogId {
46 
47   private final InternalLogId logId = InternalLogId.allocate(getClass().getName());
48   private final SubchannelPool subchannelPool;
49   private final ObjectPool<ScheduledExecutorService> timerServicePool;
50 
51   // All mutable states in this class are mutated ONLY from Channel Executor
52   private ScheduledExecutorService timerService;
53 
54   @Nullable
55   private GrpclbState grpclbState;
56 
GrpclbLoadBalancer( Helper helper, SubchannelPool subchannelPool, ObjectPool<ScheduledExecutorService> timerServicePool, TimeProvider time, BackoffPolicy.Provider backoffPolicyProvider)57   GrpclbLoadBalancer(
58       Helper helper,
59       SubchannelPool subchannelPool,
60       ObjectPool<ScheduledExecutorService> timerServicePool,
61       TimeProvider time,
62       BackoffPolicy.Provider backoffPolicyProvider) {
63     checkNotNull(helper, "helper");
64     this.timerServicePool = checkNotNull(timerServicePool, "timerServicePool");
65     this.timerService = checkNotNull(timerServicePool.getObject(), "timerService");
66     checkNotNull(time, "time provider");
67     checkNotNull(backoffPolicyProvider, "backoffPolicyProvider");
68     this.subchannelPool = checkNotNull(subchannelPool, "subchannelPool");
69     this.subchannelPool.init(helper, timerService);
70     grpclbState =
71         new GrpclbState(helper, subchannelPool, time, timerService, backoffPolicyProvider, logId);
72   }
73 
74   @Override
getLogId()75   public InternalLogId getLogId() {
76     return logId;
77   }
78 
79   @Override
handleSubchannelState(Subchannel subchannel, ConnectivityStateInfo newState)80   public void handleSubchannelState(Subchannel subchannel, ConnectivityStateInfo newState) {
81     // grpclbState should never be null here since handleSubchannelState cannot be called while the
82     // lb is shutdown.
83     grpclbState.handleSubchannelState(subchannel, newState);
84   }
85 
86   @Override
handleResolvedAddressGroups( List<EquivalentAddressGroup> updatedServers, Attributes attributes)87   public void handleResolvedAddressGroups(
88       List<EquivalentAddressGroup> updatedServers, Attributes attributes) {
89     // LB addresses and backend addresses are treated separately
90     List<LbAddressGroup> newLbAddressGroups = new ArrayList<>();
91     List<EquivalentAddressGroup> newBackendServers = new ArrayList<>();
92     for (EquivalentAddressGroup server : updatedServers) {
93       String lbAddrAuthority = server.getAttributes().get(GrpcAttributes.ATTR_LB_ADDR_AUTHORITY);
94       if (lbAddrAuthority != null) {
95         newLbAddressGroups.add(new LbAddressGroup(server, lbAddrAuthority));
96       } else {
97         newBackendServers.add(server);
98       }
99     }
100 
101     newLbAddressGroups = Collections.unmodifiableList(newLbAddressGroups);
102     newBackendServers = Collections.unmodifiableList(newBackendServers);
103     grpclbState.handleAddresses(newLbAddressGroups, newBackendServers);
104   }
105 
resetStates()106   private void resetStates() {
107     if (grpclbState != null) {
108       grpclbState.shutdown();
109       grpclbState = null;
110     }
111   }
112 
113   @Override
shutdown()114   public void shutdown() {
115     resetStates();
116     timerService = timerServicePool.returnObject(timerService);
117   }
118 
119   @Override
handleNameResolutionError(Status error)120   public void handleNameResolutionError(Status error) {
121     if (grpclbState != null) {
122       grpclbState.propagateError(error);
123     }
124   }
125 
126   @VisibleForTesting
127   @Nullable
getGrpclbState()128   GrpclbState getGrpclbState() {
129     return grpclbState;
130   }
131 }
132