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