-
Notifications
You must be signed in to change notification settings - Fork 4k
core: pass Subchannel state updates to SubchannelStateListener rather than LoadBalancer #5503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
0acae01
core: move LoadBalancer#handleSubchannelState closer to where the Sub…
zhangkun83 7cb52e1
WIP: converting implementations to new API
zhangkun83 83a05d0
New createSubchannel() will throw if not in synchronization context
zhangkun83 ddd541d
Clarify documentation
zhangkun83 d32b211
grpc-core clear
zhangkun83 4050c44
grpclb clear
zhangkun83 18f51ef
health-checking clear
zhangkun83 e56b3ed
private
zhangkun83 7086c26
Define CreateSubchannelArgs.
zhangkun83 92f26c6
Merge remote-tracking branch 'upstream/master' into handle_subchannel…
zhangkun83 6639390
CreateSubchannelArgs: copy the address list
zhangkun83 46dcbb0
Make CachedSubchannelPool always track the latest state, otherwise
zhangkun83 8a6300b
Merge remote-tracking branch 'upstream/master' into handle_subchannel…
zhangkun83 9a02be0
handleSubchannelState() doesn't throw
zhangkun83 9dcf02b
Merge branch 'handle_subchannel_state' of github.com:zhangkun83/grpc-…
zhangkun83 3c19523
Change SubchannelStateListener to an interface
zhangkun83 9da233e
Address minor comments
zhangkun83 a9fcb4a
Fix javadoc and method ordering
zhangkun83 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ | |
|
|
||
| package io.grpc; | ||
|
|
||
| import static com.google.common.base.Preconditions.checkArgument; | ||
| import static com.google.common.base.Preconditions.checkNotNull; | ||
|
|
||
| import com.google.common.base.MoreObjects; | ||
|
|
@@ -332,9 +333,17 @@ public boolean equals(Object obj) { | |
| * @param subchannel the involved Subchannel | ||
| * @param stateInfo the new state | ||
| * @since 1.2.0 | ||
| * @deprecated This method will be removed. Stop overriding it. Instead, pass {@link | ||
| * SubchannelStateListener} to {@link Helper#createSubchannel(List, Attributes, | ||
| * SubchannelStateListener)} or {@link Helper#createSubchannel(EquivalentAddressGroup, | ||
| * Attributes, SubchannelStateListener)} to receive Subchannel state updates | ||
| */ | ||
| public abstract void handleSubchannelState( | ||
| Subchannel subchannel, ConnectivityStateInfo stateInfo); | ||
| @Deprecated | ||
| public void handleSubchannelState( | ||
| Subchannel subchannel, ConnectivityStateInfo stateInfo) { | ||
| // Do nothing. If the implemetation doesn't implement this, it will get subchannel states from | ||
| // the new API. We don't throw because there may be forwarding LoadBalancers still plumb this. | ||
| } | ||
|
|
||
| /** | ||
| * The channel asks the load-balancer to shutdown. No more callbacks will be called after this | ||
|
|
@@ -648,6 +657,149 @@ public boolean equals(Object other) { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Arguments for {@link Helper#createSubchannel(CreateSubchannelArgs)}. | ||
| * | ||
| * @since 1.21.0 | ||
| */ | ||
| public static final class CreateSubchannelArgs { | ||
| private final List<EquivalentAddressGroup> addrs; | ||
| private final Attributes attrs; | ||
| private final SubchannelStateListener stateListener; | ||
|
|
||
| private CreateSubchannelArgs( | ||
| List<EquivalentAddressGroup> addrs, Attributes attrs, | ||
| SubchannelStateListener stateListener) { | ||
| this.addrs = checkNotNull(addrs, "addresses are not set"); | ||
| this.attrs = checkNotNull(attrs, "attrs"); | ||
| this.stateListener = checkNotNull(stateListener, "SubchannelStateListener is not set"); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the addresses, which is an unmodifiable list. | ||
| */ | ||
| public List<EquivalentAddressGroup> getAddresses() { | ||
| return addrs; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the attributes. | ||
| */ | ||
| public Attributes getAttributes() { | ||
| return attrs; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the state listener. | ||
| */ | ||
| public SubchannelStateListener getStateListener() { | ||
| return stateListener; | ||
| } | ||
|
|
||
| /** | ||
| * Returns a builder with the same initial values as this object. | ||
| */ | ||
| public Builder toBuilder() { | ||
| return newBuilder().setAddresses(addrs).setAttributes(attrs).setStateListener(stateListener); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new builder. | ||
| */ | ||
| public static Builder newBuilder() { | ||
| return new Builder(); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return MoreObjects.toStringHelper(this) | ||
| .add("addrs", addrs) | ||
| .add("attrs", attrs) | ||
| .add("listener", stateListener) | ||
| .toString(); | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hashCode(addrs, attrs, stateListener); | ||
| } | ||
|
|
||
| /** | ||
| * Returns true if the {@link Subchannel}, {@link Status}, and | ||
| * {@link ClientStreamTracer.Factory} all match. | ||
| */ | ||
| @Override | ||
| public boolean equals(Object other) { | ||
| if (!(other instanceof CreateSubchannelArgs)) { | ||
| return false; | ||
| } | ||
| CreateSubchannelArgs that = (CreateSubchannelArgs) other; | ||
| return Objects.equal(addrs, that.addrs) && Objects.equal(attrs, that.attrs) | ||
| && Objects.equal(stateListener, that.stateListener); | ||
| } | ||
|
|
||
| public static final class Builder { | ||
| private List<EquivalentAddressGroup> addrs; | ||
| private Attributes attrs = Attributes.EMPTY; | ||
| private SubchannelStateListener stateListener; | ||
|
|
||
| Builder() { | ||
| } | ||
|
|
||
| /** | ||
| * The addresses to connect to. All addresses are considered equivalent and will be tried | ||
| * in the order they are provided. | ||
| */ | ||
| public Builder setAddresses(EquivalentAddressGroup addrs) { | ||
| this.addrs = Collections.singletonList(addrs); | ||
| return this; | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. make Builders ctor package private
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
| /** | ||
| * The addresses to connect to. All addresses are considered equivalent and will | ||
| * be tried in the order they are provided. | ||
| * | ||
| * <p>This is a <strong>required</strong> property. | ||
| * | ||
| * @throws IllegalArgumentException if {@code addrs} is empty | ||
| */ | ||
| public Builder setAddresses(List<EquivalentAddressGroup> addrs) { | ||
| checkArgument(!addrs.isEmpty(), "addrs is empty"); | ||
| this.addrs = Collections.unmodifiableList(new ArrayList<>(addrs)); | ||
| return this; | ||
| } | ||
|
|
||
| /** | ||
| * Attributes provided here will be included in {@link Subchannel#getAttributes}. | ||
| * | ||
| * <p>This is an <strong>optional</strong> property. Default is empty if not set. | ||
| */ | ||
| public Builder setAttributes(Attributes attrs) { | ||
| this.attrs = checkNotNull(attrs, "attrs"); | ||
| return this; | ||
| } | ||
|
|
||
| /** | ||
| * Receives state changes of the created Subchannel. The listener is called from | ||
| * the {@link #getSynchronizationContext Synchronization Context}. It's safe to share the | ||
| * listener among multiple Subchannels. | ||
| * | ||
| * <p>This is a <strong>required</strong> property. | ||
| */ | ||
| public Builder setStateListener(SubchannelStateListener listener) { | ||
| this.stateListener = checkNotNull(listener, "listener"); | ||
| return this; | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new args object. | ||
| */ | ||
| public CreateSubchannelArgs build() { | ||
| return new CreateSubchannelArgs(addrs, attrs, stateListener); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Provides essentials for LoadBalancer implementations. | ||
| * | ||
|
|
@@ -661,7 +813,11 @@ public abstract static class Helper { | |
| * EquivalentAddressGroup}. | ||
| * | ||
| * @since 1.2.0 | ||
| * @deprecated Use {@link #createSubchannel(CreateSubchannelArgs)} instead. Note the new API | ||
| * must be called from {@link #getSynchronizationContext the Synchronization | ||
| * Context}. | ||
| */ | ||
| @Deprecated | ||
| public final Subchannel createSubchannel(EquivalentAddressGroup addrs, Attributes attrs) { | ||
| checkNotNull(addrs, "addrs"); | ||
| return createSubchannel(Collections.singletonList(addrs), attrs); | ||
|
|
@@ -682,11 +838,35 @@ public final Subchannel createSubchannel(EquivalentAddressGroup addrs, Attribute | |
| * | ||
| * @throws IllegalArgumentException if {@code addrs} is empty | ||
| * @since 1.14.0 | ||
| * @deprecated Use {@link #createSubchannel(CreateSubchannelArgs)} instead. Note the new API | ||
| * must be called from {@link #getSynchronizationContext the Synchronization | ||
| * Context}. | ||
| */ | ||
| @Deprecated | ||
| public Subchannel createSubchannel(List<EquivalentAddressGroup> addrs, Attributes attrs) { | ||
| throw new UnsupportedOperationException(); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a Subchannel, which is a logical connection to the given group of addresses which are | ||
| * considered equivalent. The {@code attrs} are custom attributes associated with this | ||
| * Subchannel, and can be accessed later through {@link Subchannel#getAttributes | ||
| * Subchannel.getAttributes()}. | ||
| * | ||
| * <p>This method <strong>must be called from the {@link #getSynchronizationContext | ||
| * Synchronization Context}</strong>, otherwise it may throw. This is to avoid the race between | ||
| * the caller and {@link SubchannelStateListener#onSubchannelState}. See <a | ||
| * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for more discussions. | ||
| * | ||
| * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all | ||
| * Subchannels within {@link #shutdown}. | ||
| * | ||
| * @since 1.21.0 | ||
| */ | ||
| public Subchannel createSubchannel(CreateSubchannelArgs args) { | ||
| throw new UnsupportedOperationException(); | ||
| } | ||
|
|
||
| /** | ||
| * Equivalent to {@link #updateSubchannelAddresses(io.grpc.LoadBalancer.Subchannel, List)} with | ||
| * the given single {@code EquivalentAddressGroup}. | ||
|
|
@@ -903,7 +1083,7 @@ public abstract static class Subchannel { | |
| */ | ||
| public final EquivalentAddressGroup getAddresses() { | ||
| List<EquivalentAddressGroup> groups = getAllAddresses(); | ||
| Preconditions.checkState(groups.size() == 1, "Does not have exactly one group"); | ||
| Preconditions.checkState(groups.size() == 1, "%s does not have exactly one group", groups); | ||
| return groups.get(0); | ||
| } | ||
|
|
||
|
|
@@ -964,6 +1144,39 @@ public ChannelLogger getChannelLogger() { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Receives state changes for one or more {@link Subchannel}s. All methods are run under {@link | ||
| * Helper#getSynchronizationContext}. | ||
| * | ||
| * @since 1.21.0 | ||
| */ | ||
| public interface SubchannelStateListener { | ||
|
|
||
| /** | ||
| * Handles a state change on a Subchannel. | ||
| * | ||
| * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial | ||
| * IDLE state. | ||
| * | ||
| * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link | ||
| * Helper#updateBalancingState Helper.updateBalancingState()}. Failing to do so may result in | ||
| * unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel | ||
| * PickResult.withSubchannel()}'s javadoc for more information. | ||
| * | ||
| * <p>SHUTDOWN can only happen in two cases. One is that LoadBalancer called {@link | ||
| * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel. The | ||
| * other is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has | ||
| * already terminated, thus there won't be further requests to LoadBalancer. Therefore, | ||
| * SHUTDOWN can be safely ignored. | ||
| * | ||
| * @param subchannel the involved Subchannel | ||
| * @param newState the new state | ||
| * | ||
| * @since 1.21.0 | ||
| */ | ||
| void onSubchannelState(Subchannel subchannel, ConnectivityStateInfo newState); | ||
| } | ||
|
|
||
| /** | ||
| * Factory to create {@link LoadBalancer} instance. | ||
| * | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be a copy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made Builder copy it.