• 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;
18 
19 import com.google.common.base.MoreObjects;
20 import com.google.common.base.Objects;
21 import com.google.common.base.Preconditions;
22 import java.util.Collections;
23 import java.util.List;
24 import javax.annotation.Nonnull;
25 import javax.annotation.Nullable;
26 import javax.annotation.concurrent.Immutable;
27 import javax.annotation.concurrent.NotThreadSafe;
28 import javax.annotation.concurrent.ThreadSafe;
29 
30 /**
31  * A pluggable component that receives resolved addresses from {@link NameResolver} and provides the
32  * channel a usable subchannel when asked.
33  *
34  * <h3>Overview</h3>
35  *
36  * <p>A LoadBalancer typically implements three interfaces:
37  * <ol>
38  *   <li>{@link LoadBalancer} is the main interface.  All methods on it are invoked sequentially
39  *       from the Channel Executor.  It receives the results from the {@link NameResolver}, updates
40  *       of subchannels' connectivity states, and the channel's request for the LoadBalancer to
41  *       shutdown.</li>
42  *   <li>{@link SubchannelPicker SubchannelPicker} does the actual load-balancing work.  It selects
43  *       a {@link Subchannel Subchannel} for each new RPC.</li>
44  *   <li>{@link Factory Factory} creates a new {@link LoadBalancer} instance.
45  * </ol>
46  *
47  * <p>{@link Helper Helper} is implemented by gRPC library and provided to {@link Factory
48  * Factory}. It provides functionalities that a {@code LoadBalancer} implementation would typically
49  * need.
50  *
51  * <h3>Channel Executor</h3>
52  *
53  * <p>Channel Executor is an internal executor of the channel, which is used to serialize all the
54  * callback methods on the {@link LoadBalancer} interface, thus the balancer implementation doesn't
55  * need to worry about synchronization among them.  However, the actual thread of the Channel
56  * Executor is typically the network thread, thus the following rules must be followed to prevent
57  * blocking or even dead-locking in a network
58  *
59  * <ol>
60  *
61  *   <li><strong>Never block in Channel Executor</strong>.  The callback methods must return
62  *   quickly.  Examples or work that must be avoided: CPU-intensive calculation, waiting on
63  *   synchronization primitives, blocking I/O, blocking RPCs, etc.</li>
64  *
65  *   <li><strong>Avoid calling into other components with lock held</strong>.  Channel Executor may
66  *   run callbacks under a lock, e.g., the transport lock of OkHttp.  If your LoadBalancer has a
67  *   lock, holds the lock in a callback method (e.g., {@link #handleSubchannelState
68  *   handleSubchannelState()}) while calling into another class that may involve locks, be cautious
69  *   of deadlock.  Generally you wouldn't need any locking in the LoadBalancer.</li>
70  *
71  * </ol>
72  *
73  * <p>{@link Helper#runSerialized Helper.runSerialized()} allows you to schedule a task to be run in
74  * the Channel Executor.
75  *
76  * <h3>The canonical implementation pattern</h3>
77  *
78  * <p>A {@link LoadBalancer} keeps states like the latest addresses from NameResolver, the
79  * Subchannel(s) and their latest connectivity states.  These states are mutated within the Channel
80  * Executor.
81  *
82  * <p>A typical {@link SubchannelPicker SubchannelPicker} holds a snapshot of these states.  It may
83  * have its own states, e.g., a picker from a round-robin load-balancer may keep a pointer to the
84  * next Subchannel, which are typically mutated by multiple threads.  The picker should only mutate
85  * its own state, and should not mutate or re-acquire the states of the LoadBalancer.  This way the
86  * picker only needs to synchronize its own states, which is typically trivial to implement.
87  *
88  * <p>When the LoadBalancer states changes, e.g., Subchannels has become or stopped being READY, and
89  * we want subsequent RPCs to use the latest list of READY Subchannels, LoadBalancer would create
90  * a new picker, which holds a snapshot of the latest Subchannel list.  Refer to the javadoc of
91  * {@link #handleSubchannelState handleSubchannelState()} how to do this properly.
92  *
93  * <p>No synchronization should be necessary between LoadBalancer and its pickers if you follow
94  * the pattern above.  It may be possible to implement in a different way, but that would usually
95  * result in more complicated threading.
96  *
97  * @since 1.2.0
98  */
99 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
100 @NotThreadSafe
101 public abstract class LoadBalancer {
102   /**
103    * Handles newly resolved server groups and metadata attributes from name resolution system.
104    * {@code servers} contained in {@link EquivalentAddressGroup} should be considered equivalent
105    * but may be flattened into a single list if needed.
106    *
107    * <p>Implementations should not modify the given {@code servers}.
108    *
109    * @param servers the resolved server addresses, never empty.
110    * @param attributes extra information from naming system.
111    * @since 1.2.0
112    */
handleResolvedAddressGroups( List<EquivalentAddressGroup> servers, @NameResolver.ResolutionResultAttr Attributes attributes)113   public abstract void handleResolvedAddressGroups(
114       List<EquivalentAddressGroup> servers,
115       @NameResolver.ResolutionResultAttr Attributes attributes);
116 
117   /**
118    * Handles an error from the name resolution system.
119    *
120    * @param error a non-OK status
121    * @since 1.2.0
122    */
handleNameResolutionError(Status error)123   public abstract void handleNameResolutionError(Status error);
124 
125   /**
126    * Handles a state change on a Subchannel.
127    *
128    * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial IDLE
129    * state.
130    *
131    * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link
132    * Helper#updateBalancingState Helper.updateBalancingState()}.  Failing to do so may result in
133    * unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel
134    * PickResult.withSubchannel()}'s javadoc for more information.
135    *
136    * <p>SHUTDOWN can only happen in two cases.  One is that LoadBalancer called {@link
137    * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel.  The other
138    * is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has already
139    * terminated, thus there won't be further requests to LoadBalancer.  Therefore, SHUTDOWN can be
140    * safely ignored.
141    *
142    * @param subchannel the involved Subchannel
143    * @param stateInfo the new state
144    * @since 1.2.0
145    */
handleSubchannelState( Subchannel subchannel, ConnectivityStateInfo stateInfo)146   public abstract void handleSubchannelState(
147       Subchannel subchannel, ConnectivityStateInfo stateInfo);
148 
149   /**
150    * The channel asks the load-balancer to shutdown.  No more callbacks will be called after this
151    * method.  The implementation should shutdown all Subchannels and OOB channels, and do any other
152    * cleanup as necessary.
153    *
154    * @since 1.2.0
155    */
shutdown()156   public abstract void shutdown();
157 
158   @Override
toString()159   public String toString() {
160     return getClass().getSimpleName();
161   }
162 
163   /**
164    * The main balancing logic.  It <strong>must be thread-safe</strong>. Typically it should only
165    * synchronize on its own state, and avoid synchronizing with the LoadBalancer's state.
166    *
167    * @since 1.2.0
168    */
169   @ThreadSafe
170   public abstract static class SubchannelPicker {
171     /**
172      * Make a balancing decision for a new RPC.
173      *
174      * @param args the pick arguments
175      * @since 1.3.0
176      */
pickSubchannel(PickSubchannelArgs args)177     public abstract PickResult pickSubchannel(PickSubchannelArgs args);
178 
179     /**
180      * Tries to establish connections now so that the upcoming RPC may then just pick a ready
181      * connection without having to connect first.
182      *
183      * <p>No-op if unsupported.
184      *
185      * @since 1.11.0
186      */
requestConnection()187     public void requestConnection() {}
188   }
189 
190   /**
191    * Provides arguments for a {@link SubchannelPicker#pickSubchannel(
192    * LoadBalancer.PickSubchannelArgs)}.
193    *
194    * @since 1.2.0
195    */
196   public abstract static class PickSubchannelArgs {
197 
198     /**
199      * Call options.
200      *
201      * @since 1.2.0
202      */
getCallOptions()203     public abstract CallOptions getCallOptions();
204 
205     /**
206      * Headers of the call. {@link SubchannelPicker#pickSubchannel} may mutate it before before
207      * returning.
208      *
209      * @since 1.2.0
210      */
getHeaders()211     public abstract Metadata getHeaders();
212 
213     /**
214      * Call method.
215      *
216      * @since 1.2.0
217      */
getMethodDescriptor()218     public abstract MethodDescriptor<?, ?> getMethodDescriptor();
219   }
220 
221   /**
222    * A balancing decision made by {@link SubchannelPicker SubchannelPicker} for an RPC.
223    *
224    * <p>The outcome of the decision will be one of the following:
225    * <ul>
226    *   <li>Proceed: if a Subchannel is provided via {@link #withSubchannel withSubchannel()}, and is
227    *       in READY state when the RPC tries to start on it, the RPC will proceed on that
228    *       Subchannel.</li>
229    *   <li>Error: if an error is provided via {@link #withError withError()}, and the RPC is not
230    *       wait-for-ready (i.e., {@link CallOptions#withWaitForReady} was not called), the RPC will
231    *       fail immediately with the given error.</li>
232    *   <li>Buffer: in all other cases, the RPC will be buffered in the Channel, until the next
233    *       picker is provided via {@link Helper#updateBalancingState Helper.updateBalancingState()},
234    *       when the RPC will go through the same picking process again.</li>
235    * </ul>
236    *
237    * @since 1.2.0
238    */
239   @Immutable
240   public static final class PickResult {
241     private static final PickResult NO_RESULT = new PickResult(null, null, Status.OK, false);
242 
243     @Nullable private final Subchannel subchannel;
244     @Nullable private final ClientStreamTracer.Factory streamTracerFactory;
245     // An error to be propagated to the application if subchannel == null
246     // Or OK if there is no error.
247     // subchannel being null and error being OK means RPC needs to wait
248     private final Status status;
249     // True if the result is created by withDrop()
250     private final boolean drop;
251 
PickResult( @ullable Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory, Status status, boolean drop)252     private PickResult(
253         @Nullable Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory,
254         Status status, boolean drop) {
255       this.subchannel = subchannel;
256       this.streamTracerFactory = streamTracerFactory;
257       this.status = Preconditions.checkNotNull(status, "status");
258       this.drop = drop;
259     }
260 
261     /**
262      * A decision to proceed the RPC on a Subchannel.
263      *
264      * <p>Only Subchannels returned by {@link Helper#createSubchannel Helper.createSubchannel()}
265      * will work.  DO NOT try to use your own implementations of Subchannels, as they won't work.
266      *
267      * <p>When the RPC tries to use the return Subchannel, which is briefly after this method
268      * returns, the state of the Subchannel will decide where the RPC would go:
269      *
270      * <ul>
271      *   <li>READY: the RPC will proceed on this Subchannel.</li>
272      *   <li>IDLE: the RPC will be buffered.  Subchannel will attempt to create connection.</li>
273      *   <li>All other states: the RPC will be buffered.</li>
274      * </ul>
275      *
276      * <p><strong>All buffered RPCs will stay buffered</strong> until the next call of {@link
277      * Helper#updateBalancingState Helper.updateBalancingState()}, which will trigger a new picking
278      * process.
279      *
280      * <p>Note that Subchannel's state may change at the same time the picker is making the
281      * decision, which means the decision may be made with (to-be) outdated information.  For
282      * example, a picker may return a Subchannel known to be READY, but it has become IDLE when is
283      * about to be used by the RPC, which makes the RPC to be buffered.  The LoadBalancer will soon
284      * learn about the Subchannels' transition from READY to IDLE, create a new picker and allow the
285      * RPC to use another READY transport if there is any.
286      *
287      * <p>You will want to avoid running into a situation where there are READY Subchannels out
288      * there but some RPCs are still buffered for longer than a brief time.
289      * <ul>
290      *   <li>This can happen if you return Subchannels with states other than READY and IDLE.  For
291      *       example, suppose you round-robin on 2 Subchannels, in READY and CONNECTING states
292      *       respectively.  If the picker ignores the state and pick them equally, 50% of RPCs will
293      *       be stuck in buffered state until both Subchannels are READY.</li>
294      *   <li>This can also happen if you don't create a new picker at key state changes of
295      *       Subchannels.  Take the above round-robin example again.  Suppose you do pick only READY
296      *       and IDLE Subchannels, and initially both Subchannels are READY.  Now one becomes IDLE,
297      *       then CONNECTING and stays CONNECTING for a long time.  If you don't create a new picker
298      *       in response to the CONNECTING state to exclude that Subchannel, 50% of RPCs will hit it
299      *       and be buffered even though the other Subchannel is READY.</li>
300      * </ul>
301      *
302      * <p>In order to prevent unnecessary delay of RPCs, the rules of thumb are:
303      * <ol>
304      *   <li>The picker should only pick Subchannels that are known as READY or IDLE.  Whether to
305      *       pick IDLE Subchannels depends on whether you want Subchannels to connect on-demand or
306      *       actively:
307      *       <ul>
308      *         <li>If you want connect-on-demand, include IDLE Subchannels in your pick results,
309      *             because when an RPC tries to use an IDLE Subchannel, the Subchannel will try to
310      *             connect.</li>
311      *         <li>If you want Subchannels to be always connected even when there is no RPC, you
312      *             would call {@link Subchannel#requestConnection Subchannel.requestConnection()}
313      *             whenever the Subchannel has transitioned to IDLE, then you don't need to include
314      *             IDLE Subchannels in your pick results.</li>
315      *       </ul></li>
316      *   <li>Always create a new picker and call {@link Helper#updateBalancingState
317      *       Helper.updateBalancingState()} whenever {@link #handleSubchannelState
318      *       handleSubchannelState()} is called, unless the new state is SHUTDOWN. See
319      *       {@code handleSubchannelState}'s javadoc for more details.</li>
320      * </ol>
321      *
322      * @param subchannel the picked Subchannel
323      * @param streamTracerFactory if not null, will be used to trace the activities of the stream
324      *                            created as a result of this pick. Note it's possible that no
325      *                            stream is created at all in some cases.
326      * @since 1.3.0
327      */
withSubchannel( Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory)328     public static PickResult withSubchannel(
329         Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory) {
330       return new PickResult(
331           Preconditions.checkNotNull(subchannel, "subchannel"), streamTracerFactory, Status.OK,
332           false);
333     }
334 
335     /**
336      * Equivalent to {@code withSubchannel(subchannel, null)}.
337      *
338      * @since 1.2.0
339      */
withSubchannel(Subchannel subchannel)340     public static PickResult withSubchannel(Subchannel subchannel) {
341       return withSubchannel(subchannel, null);
342     }
343 
344     /**
345      * A decision to report a connectivity error to the RPC.  If the RPC is {@link
346      * CallOptions#withWaitForReady wait-for-ready}, it will stay buffered.  Otherwise, it will fail
347      * with the given error.
348      *
349      * @param error the error status.  Must not be OK.
350      * @since 1.2.0
351      */
withError(Status error)352     public static PickResult withError(Status error) {
353       Preconditions.checkArgument(!error.isOk(), "error status shouldn't be OK");
354       return new PickResult(null, null, error, false);
355     }
356 
357     /**
358      * A decision to fail an RPC immediately.  This is a final decision and will ignore retry
359      * policy.
360      *
361      * @param status the status with which the RPC will fail.  Must not be OK.
362      * @since 1.8.0
363      */
withDrop(Status status)364     public static PickResult withDrop(Status status) {
365       Preconditions.checkArgument(!status.isOk(), "drop status shouldn't be OK");
366       return new PickResult(null, null, status, true);
367     }
368 
369     /**
370      * No decision could be made.  The RPC will stay buffered.
371      *
372      * @since 1.2.0
373      */
withNoResult()374     public static PickResult withNoResult() {
375       return NO_RESULT;
376     }
377 
378     /**
379      * The Subchannel if this result was created by {@link #withSubchannel withSubchannel()}, or
380      * null otherwise.
381      *
382      * @since 1.2.0
383      */
384     @Nullable
getSubchannel()385     public Subchannel getSubchannel() {
386       return subchannel;
387     }
388 
389     /**
390      * The stream tracer factory this result was created with.
391      *
392      * @since 1.3.0
393      */
394     @Nullable
getStreamTracerFactory()395     public ClientStreamTracer.Factory getStreamTracerFactory() {
396       return streamTracerFactory;
397     }
398 
399     /**
400      * The status associated with this result.  Non-{@code OK} if created with {@link #withError
401      * withError}, or {@code OK} otherwise.
402      *
403      * @since 1.2.0
404      */
getStatus()405     public Status getStatus() {
406       return status;
407     }
408 
409     /**
410      * Returns {@code true} if this result was created by {@link #withDrop withDrop()}.
411      *
412      * @since 1.8.0
413      */
isDrop()414     public boolean isDrop() {
415       return drop;
416     }
417 
418     @Override
toString()419     public String toString() {
420       return MoreObjects.toStringHelper(this)
421           .add("subchannel", subchannel)
422           .add("streamTracerFactory", streamTracerFactory)
423           .add("status", status)
424           .add("drop", drop)
425           .toString();
426     }
427 
428     @Override
hashCode()429     public int hashCode() {
430       return Objects.hashCode(subchannel, status, streamTracerFactory, drop);
431     }
432 
433     /**
434      * Returns true if the {@link Subchannel}, {@link Status}, and
435      * {@link ClientStreamTracer.Factory} all match.
436      */
437     @Override
equals(Object other)438     public boolean equals(Object other) {
439       if (!(other instanceof PickResult)) {
440         return false;
441       }
442       PickResult that = (PickResult) other;
443       return Objects.equal(subchannel, that.subchannel) && Objects.equal(status, that.status)
444           && Objects.equal(streamTracerFactory, that.streamTracerFactory)
445           && drop == that.drop;
446     }
447   }
448 
449   /**
450    * Provides essentials for LoadBalancer implementations.
451    *
452    * @since 1.2.0
453    */
454   @ThreadSafe
455   public abstract static class Helper {
456     /**
457      * Creates a Subchannel, which is a logical connection to the given group of addresses which are
458      * considered equivalent.  The {@code attrs} are custom attributes associated with this
459      * Subchannel, and can be accessed later through {@link Subchannel#getAttributes
460      * Subchannel.getAttributes()}.
461      *
462      * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
463      * Subchannels within {@link #shutdown}.
464      *
465      * <p>The default implementation calls {@link #createSubchannel(List, Attributes)}.
466      * Implementations should not override this method.
467      *
468      * @since 1.2.0
469      */
createSubchannel(EquivalentAddressGroup addrs, Attributes attrs)470     public Subchannel createSubchannel(EquivalentAddressGroup addrs, Attributes attrs) {
471       Preconditions.checkNotNull(addrs, "addrs");
472       return createSubchannel(Collections.singletonList(addrs), attrs);
473     }
474 
475     /**
476      * Creates a Subchannel, which is a logical connection to the given group of addresses which are
477      * considered equivalent.  The {@code attrs} are custom attributes associated with this
478      * Subchannel, and can be accessed later through {@link Subchannel#getAttributes
479      * Subchannel.getAttributes()}.
480      *
481      * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
482      * Subchannels within {@link #shutdown}.
483      *
484      * @throws IllegalArgumentException if {@code addrs} is empty
485      * @since 1.14.0
486      */
createSubchannel(List<EquivalentAddressGroup> addrs, Attributes attrs)487     public Subchannel createSubchannel(List<EquivalentAddressGroup> addrs, Attributes attrs) {
488       throw new UnsupportedOperationException();
489     }
490 
491     /**
492      * Replaces the existing addresses used with {@code subchannel}. This method is superior to
493      * {@link #createSubchannel} when the new and old addresses overlap, since the subchannel can
494      * continue using an existing connection.
495      *
496      * <p>The default implementation calls {@link #updateSubchannelAddresses(
497      * LoadBalancer.Subchannel, List)}. Implementations should not override this method.
498      *
499      * @throws IllegalArgumentException if {@code subchannel} was not returned from {@link
500      *     #createSubchannel}
501      * @since 1.4.0
502      */
updateSubchannelAddresses( Subchannel subchannel, EquivalentAddressGroup addrs)503     public void updateSubchannelAddresses(
504         Subchannel subchannel, EquivalentAddressGroup addrs) {
505       Preconditions.checkNotNull(addrs, "addrs");
506       updateSubchannelAddresses(subchannel, Collections.singletonList(addrs));
507     }
508 
509     /**
510      * Replaces the existing addresses used with {@code subchannel}. This method is superior to
511      * {@link #createSubchannel} when the new and old addresses overlap, since the subchannel can
512      * continue using an existing connection.
513      *
514      * @throws IllegalArgumentException if {@code subchannel} was not returned from {@link
515      *     #createSubchannel} or {@code addrs} is empty
516      * @since 1.14.0
517      */
updateSubchannelAddresses( Subchannel subchannel, List<EquivalentAddressGroup> addrs)518     public void updateSubchannelAddresses(
519         Subchannel subchannel, List<EquivalentAddressGroup> addrs) {
520       throw new UnsupportedOperationException();
521     }
522 
523     /**
524      * Out-of-band channel for LoadBalancer’s own RPC needs, e.g., talking to an external
525      * load-balancer service.
526      *
527      * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
528      * channels within {@link #shutdown}.
529      *
530      * @since 1.4.0
531      */
532     // TODO(ejona): Allow passing a List<EAG> here and to updateOobChannelAddresses, but want to
533     // wait until https://github.com/grpc/grpc-java/issues/4469 is done.
534     // https://github.com/grpc/grpc-java/issues/4618
createOobChannel(EquivalentAddressGroup eag, String authority)535     public abstract ManagedChannel createOobChannel(EquivalentAddressGroup eag, String authority);
536 
537     /**
538      * Updates the addresses used for connections in the {@code Channel}. This is supperior to
539      * {@link #createOobChannel} when the old and new addresses overlap, since the channel can
540      * continue using an existing connection.
541      *
542      * @throws IllegalArgumentException if {@code channel} was not returned from {@link
543      *     #createOobChannel}
544      * @since 1.4.0
545      */
updateOobChannelAddresses(ManagedChannel channel, EquivalentAddressGroup eag)546     public void updateOobChannelAddresses(ManagedChannel channel, EquivalentAddressGroup eag) {
547       throw new UnsupportedOperationException();
548     }
549 
550     /**
551      * Set a new state with a new picker to the channel.
552      *
553      * <p>When a new picker is provided via {@code updateBalancingState()}, the channel will apply
554      * the picker on all buffered RPCs, by calling {@link SubchannelPicker#pickSubchannel(
555      * LoadBalancer.PickSubchannelArgs)}.
556      *
557      * <p>The channel will hold the picker and use it for all RPCs, until {@code
558      * updateBalancingState()} is called again and a new picker replaces the old one.  If {@code
559      * updateBalancingState()} has never been called, the channel will buffer all RPCs until a
560      * picker is provided.
561      *
562      * <p>The passed state will be the channel's new state. The SHUTDOWN state should not be passed
563      * and its behavior is undefined.
564      *
565      * @since 1.6.0
566      */
updateBalancingState( @onnull ConnectivityState newState, @Nonnull SubchannelPicker newPicker)567     public abstract void updateBalancingState(
568         @Nonnull ConnectivityState newState, @Nonnull SubchannelPicker newPicker);
569 
570     /**
571      * Schedule a task to be run in the Channel Executor, which serializes the task with the
572      * callback methods on the {@link LoadBalancer} interface.
573      *
574      * @since 1.2.0
575      */
runSerialized(Runnable task)576     public abstract void runSerialized(Runnable task);
577 
578     /**
579      * Returns the NameResolver of the channel.
580      *
581      * @since 1.2.0
582      */
getNameResolverFactory()583     public abstract NameResolver.Factory getNameResolverFactory();
584 
585     /**
586      * Returns the authority string of the channel, which is derived from the DNS-style target name.
587      *
588      * @since 1.2.0
589      */
getAuthority()590     public abstract String getAuthority();
591   }
592 
593   /**
594    * A logical connection to a server, or a group of equivalent servers represented by an {@link
595    * EquivalentAddressGroup}.
596    *
597    * <p>It maintains at most one physical connection (aka transport) for sending new RPCs, while
598    * also keeps track of previous transports that has been shut down but not terminated yet.
599    *
600    * <p>If there isn't an active transport yet, and an RPC is assigned to the Subchannel, it will
601    * create a new transport.  It won't actively create transports otherwise.  {@link
602    * #requestConnection requestConnection()} can be used to ask Subchannel to create a transport if
603    * there isn't any.
604    *
605    * @since 1.2.0
606    */
607   @ThreadSafe
608   public abstract static class Subchannel {
609     /**
610      * Shuts down the Subchannel.  After this method is called, this Subchannel should no longer
611      * be returned by the latest {@link SubchannelPicker picker}, and can be safely discarded.
612      *
613      * @since 1.2.0
614      */
shutdown()615     public abstract void shutdown();
616 
617     /**
618      * Asks the Subchannel to create a connection (aka transport), if there isn't an active one.
619      *
620      * @since 1.2.0
621      */
requestConnection()622     public abstract void requestConnection();
623 
624     /**
625      * Returns the addresses that this Subchannel is bound to. The default implementation calls
626      * getAllAddresses().
627      *
628      * <p>The default implementation calls {@link #getAllAddresses()}. Implementations should not
629      * override this method.
630      *
631      * @throws IllegalStateException if this subchannel has more than one EquivalentAddressGroup.
632      *     Use getAllAddresses() instead
633      * @since 1.2.0
634      */
getAddresses()635     public EquivalentAddressGroup getAddresses() {
636       List<EquivalentAddressGroup> groups = getAllAddresses();
637       Preconditions.checkState(groups.size() == 1, "Does not have exactly one group");
638       return groups.get(0);
639     }
640 
641     /**
642      * Returns the addresses that this Subchannel is bound to. The returned list will not be empty.
643      *
644      * @since 1.14.0
645      */
getAllAddresses()646     public List<EquivalentAddressGroup> getAllAddresses() {
647       throw new UnsupportedOperationException();
648     }
649 
650     /**
651      * The same attributes passed to {@link Helper#createSubchannel Helper.createSubchannel()}.
652      * LoadBalancer can use it to attach additional information here, e.g., the shard this
653      * Subchannel belongs to.
654      *
655      * @since 1.2.0
656      */
getAttributes()657     public abstract Attributes getAttributes();
658   }
659 
660   /**
661    * Factory to create {@link LoadBalancer} instance.
662    *
663    * @since 1.2.0
664    */
665   @ThreadSafe
666   public abstract static class Factory {
667     /**
668      * Creates a {@link LoadBalancer} that will be used inside a channel.
669      *
670      * @since 1.2.0
671      */
newLoadBalancer(Helper helper)672     public abstract LoadBalancer newLoadBalancer(Helper helper);
673   }
674 }
675