grpc-java icon indicating copy to clipboard operation
grpc-java copied to clipboard

ConnectivityStateManager Status notification problem

Open hlx502 opened this issue 1 year ago • 3 comments

  1. Why does notifyWhenStateChanged() execute callback immediately when state != source? image
  2. Do we need to clear listeners for each state change? image

hlx502 avatar Oct 15 '24 07:10 hlx502

From the Javadoc:

Registers a one-off callback that will be run if the connectivity state of the channel diverges from the given source, which is typically what has just been returned by getState(boolean). If the states are already different, the callback will be called immediately.

What do you hope the passed source is used for? source is what you think the current state is, and the callback is called when the channel is no longer that state. The API is inherently (and purposefully) racy, and accounts for that race by immediately notifying if source is out-of-date.

ejona86 avatar Oct 15 '24 14:10 ejona86

Understood. Our client uses a domain name to connect to the server, but the server IP may change, such as in the k8s environment. When reconnecting through the automatic reconnection mechanism, the IP cannot be resolved based on the domain name. We will manually rebuild the channel based on its status, but it seems that notifyWhenStateChanged cannot be used. Do you have any suggestions on your end? Thanks

hlx502 avatar Oct 16 '24 02:10 hlx502

the IP cannot be resolved based on the domain name

Why not? The client will re-resolve DNS when a connection is dropped/failed. So it will do the same as you're wanting to do.

If there's only one IP, then a regular k8s service should be fine; you wouldn't benefit from a headless service.

but it seems that notifyWhenStateChanged cannot be used

You can learn about TRANSIENT_FAILURE...

private void handleStateChange() {
  ConnectivityState state = channel.getState(false);
  if (state == TRANSIENT_FAILURE) {
    // react
  } else {
    channel.notifyWhenStateChanged(state, this::handleStateChange);
  }
}

channel.notifyWhenStateChanged(ConnectivityState.IDLE, this::handleStateChange);

Not that I'd encourage doing that to tear down the channel. If you do that, at the very least double-check that the address has actually changed before throwing away the TRANSIENT_FAILURE channel.

ejona86 avatar Oct 16 '24 15:10 ejona86

No response, and seems like this could be resolved. If not, comment, and it can be reopened.

ejona86 avatar Nov 12 '24 18:11 ejona86