Skip to content

Conversation

dapengzhang0
Copy link
Contributor

No description provided.

@dapengzhang0 dapengzhang0 requested a review from zhangkun83 August 2, 2017 17:34
if (subchannel == null) {
subchannel = helper.createSubchannel(newEag, Attributes.EMPTY);
helper.updatePicker(new Picker(PickResult.withSubchannel(subchannel)));
helper.updateBalancingState(CONNECTING, new Picker(PickResult.withSubchannel(subchannel)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new subchannel won't try to connect until an RPC is started.
The initial state of a new subchannel is IDLE. This should pass IDLE.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initial state of ManagedChannelImpl is IDLE. I think the method handleResolvedAddressGroups() wouldn't happen before NameResolver.start(), which wouldn't happen before ManagedChannelImpl.exitIdle(). So it should not be IDLE when this method is called.

}
if (currentState == SHUTDOWN) {
// Either IDLE_TIMEOUT or channel is shutdown. Won't have any effect for the latter case.
helper.updateBalancingState(IDLE, new Picker(PickResult.withNoResult()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDLE_TIMEOUT is completely a channel impl logic. Even if we wanted to expose it to the application, it should be channel impl that would do that, i.e., transit to IDLE when IdleModeTimer expires and ignore updates from balancer if it's not the current one (which channel impl should be probably doing in the first place).

The balancer should not assume the channel's state. It should only provide state from its own perspective.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Fixed

nameResolver.shutdown();
nameResolver = getNameResolver(target, nameResolverFactory, nameResolverParams);
loadBalancer.shutdown();
loadBalancer = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In LbHelperImpl.updateBalancingState(), the state and the picker should be ignored if loadBalancer != lb, so that the channel ignores any updates from a balancer that has been shutdown and discarded.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this code in ManagedChannelImpl:

LbHelperImpl helper = new LbHelperImpl(nameResolver);
helper.lb = loadBalancerFactory.newLoadBalancer(helper);
this.loadBalancer = helper.lb;

Because ManagedChannelImpl does not own loadBalancerFactory, it does not know the behavior of loadBalancerFactory.newLoadBalancer(), which may just always recycle the old loadBalancer and restart it so that loadBalancer == lb is always true.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A factory that recycles the instances is violating the API. If the factory is shared among multiple channels, worse things will happen anyway. I don't think we should worry about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the factory is shared among multiple channels, it's not worse as long as the factory only recycles the completely shutdown ones.

What about letting ManagedChannelImpl have a helper field instead of loadBalancer field. And in LbHelperImpl, checking this == ManagedChannelImpl.this.helper instead of checking loadBalancer == lb?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds fine.

checkNotNull(newState, "newState");
checkNotNull(newPicker, "newPicker");

if (this != lbHelper) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lbHelper must be accessed from channelExecutor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected. PTAL

@Deprecated
@Override
public void updatePicker(final SubchannelPicker picker) {
if (this != lbHelper) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor

@zhangkun83 zhangkun83 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the description to include all changes.

@dapengzhang0
Copy link
Contributor Author

retest this please

@dapengzhang0 dapengzhang0 merged commit 04fd4bc into grpc:master Aug 10, 2017
@dapengzhang0 dapengzhang0 deleted the pickfirst branch August 13, 2017 05:14
@lock lock bot locked as resolved and limited conversation to collaborators Jan 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants