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