-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Provide hook for network availability notification on Android #2169
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
Comments
There is exponential backoff in play. We'd like to provide a hook that allows interacting with Android's network notification, but that isn't available right now. CC @zsurocking |
Thanks! I new a channel each time to avoid exponential backoff. And there are other problems confuse me when i new channel : When i new a channel ,is it reference to same transport ? Dose the approach has a performance overhead? Will the hook that allows interacting with Android's network notification provide in v1.0.x? |
It will create a new transport and a new connection. And yes, it has performance overhead. A quick workaround might be monitoring the network yourself and starts a new channel when wifi connects. |
Thanks your help . |
Having this functionality would be immensely useful for my Android use case as well. Have implementation plans become more concrete? Could there be an option to offer a more aggressive backoff strategy for Android/OkHttp in the meantime? Is backoff carried over to future connection attempts right now, instead of resetting the backoff to 0 on success? If the current exponential backoff mechanism focuses on not overloading a busy server with requests it may be misplaced when the client is Android. I'd think in most connectivity cases it's the mobile client that has issues (namely with the network, especially away from WiFi), not the server being overloaded. At least that would be true for my use case, where I control the server. And I'd much prefer my server getting hammered on occasion over my client being unresponsive all the time. With a flaky network or scheduled execution I'd need to reconnect as soon as I'm back online to not miss the connectivity window. I guess the network monitoring hook would address this need. |
We are actively working on the design for this: initially we are likely to just provide a "network available" hook that apps can use to notify the channel when the network is back, and this will reset any backoff and DNS resolution timers so the channel can attempt to reconnect immediately. There are other, potentially more involved interactions with network availability on Android (or elsewhere) that we want to make sure the API can also support in the future.
In my experience you are much more likely to run into these problems due to the DNS resolution timer when the network is down, rather than the exponential backoff on the reconnection attempt (DNS resolution failures shutdown the subchannel, stopping the reconnection attempts). The DNS resolution backoff is specific to the channel, so creating a new channel as soon as the network comes back will successfully connect when you send an RPC. The API addition discussed here will remove the need to create a new channel to short-circuit these two sources of backoff and delay in sending RPCs on a pre-existing channel.
This is a fair point, but there are also battery use implications of just retrying in a tight loop, especially when the network is down. Our current backoffs are not necessarily ideal for Android, but they should be pretty adequate as long as the network itself on the device is not going in and out of a connected state - and the network availability hook will "catch" this case by allowing a reset of the backoff timers. |
That's great to hear about this having some momentum, thank you for the valuable information and all the good work! I should add my (simplified) use case to make it clear where I'm coming from: I have an existing non-grpc design that I need to replace (for unrelated reasons). It does not use Android's network availability notifications. It's a kind of navigation app which syncs with a server periodically, using a synchronous request-response mechanism. If the network is down it will miss a sync, but a future sync will make up for it. It's a simple but resilient approach, and the lack of backoff does not change the battery picture much under the assumption that the network will be available most of the time. Using Android's network availability hints would complicate the design without much real gain. If I transferred this design to grpc as-is, then the backoff policy would get in the way, especially when the network goes in and out of a connected state, and it would cause both less timely and less successful syncs than what would generally be achievable. This is true for my legacy design as well, but additional backoff would exacerbate the problem. For my flavor of navigation app, timely syncs are very important, and I do anticipate flaky networks in my target environment (out in the wild). I am not planning to transfer the design as-is, but use a client-streaming RPC instead. This should provide a more elegant approach, but will require an adequate backoff strategy. I expect the network availability notification hook to go a long way to a good user experience. My app will have other RPCs, complicating the picture for channel re-creation workarounds in my mind. Based on the earlier information from the linked issue I've switched to using IP addresses to hopefully preempt the DNS resolution problem. |
One thing I wanted to add to complete the picture - please keep in mind the Android JobScheduler use case (or similar scheduled execution cases). JobScheduler-triggered grpc calls need to retry a connection without backoff (and preferably attempt a second timely retry, because Android), as the available scheduled time window is small. And in general there is no reason to create a separate channel & connection just because execution is triggered by JobScheduler; a channel can (and probably should) be shared with other code. In fact, in my actual use case I can have calls triggered from non-scheduled code and other calls triggered from JobScheduler at the same time. The notification hook design may support this, I just wanted to make the use case explicit as a variation of network availability notification. |
@ericgribkoff @ejona86 any update on this ? We need some options here |
I wonder if it's possible to implement your own NameResolver to work around the built-in DNS Name Resolver backoff. Haven't tried it, but it crossed my mind. If you don't need TLS then using straight IPs during Channel setup might possibly help, too. Otherwise I've had fancy thoughts about creating my own LoadBalancer and shifting calls over to a new Subchannel when I detect network changes. This may be a relevant general pattern for Android, as you can have network changes between cellular data & WiFi, at which point you'd want to proactively start new calls on the new network, while letting calls on the old network connection complete without killing them. (The network availability hook would seem to come into play here again.) Or if you get an error or unresponsiveness which could be due to your network connection gone bad, you could quickly launch a new Subchannel without tearing down and recreating the whole Channel for more control. I'm not sure how feasible this really is, though. I will likely create a few separate issues for this and other enhancements in the coming weeks. |
I haven't had the chance to work further on this yet. It's still on my task list, but I have some higher priority items that have taken precedence for the moment. FYI Cronet, which is being open-sourced for gRPC in #3349, already includes some pretty sophisticated network availability monitoring on Android that gRPC gets for free when using Cronet as the transport. |
The API in #3580 may be a bit annoying for applications to use, as users will have to plumb the notification through their code to all channels. We may consider alternative approaches. |
We have been waiting for this one and the support for <21 devices. We gave up already on supporting <21 devices because of the complexity of adding all those conscrypt libraries :(. |
FWIW: the API in #3580 would seem to address my needs. I've ended up with wait-for-ready semantics for all calls and it appears the two would play together well. Common usages for the new API on Android would be from network availability broadcast receivers and JobScheduler-style invocations, both of which look compatible. |
I new a stub with a multiplexed channel like this:
Launch the application when the network is close , then open the network . Invoking method of stub that is built with a multiplex don`t work immediately. While invoking method of stub that built with new channel can get response from server immediately . It will happen also when the network was unavailable long time .and then network turn available .
How does channel judge network state ?How to reconnect immediately with multiplexed channel ?
Build and platform infomation:
application is running in Android 5.1.1 and 6.0.1
Thanks !
The text was updated successfully, but these errors were encountered: