Skip to content

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

Closed
HugeTimor opened this issue Aug 17, 2016 · 15 comments
Closed

Provide hook for network availability notification on Android #2169

HugeTimor opened this issue Aug 17, 2016 · 15 comments
Assignees
Milestone

Comments

@HugeTimor
Copy link

I new a stub with a multiplexed channel like this:

ServiceGrpc.ServiceBlockingStub stub = ServiceGrpc.newBlockingStub(getChannel());
 public static ManagedChannel getChannel() {
        if (mChannel == null) {
            mChannel = ManagedChannelBuilder.forAddress(Config.HOST, Config.PORT)
                    .usePlaintext(true)
                    .build();
        }
        return mChannel;
    }

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:

            compileSdkVersion: 23,
            buildToolsVersion: "23.0.2",
            minSdkVersion    : 14,
            targetSdkVersion : 19,

application is running in Android 5.1.1 and 6.0.1

Thanks !

@ejona86
Copy link
Member

ejona86 commented Aug 17, 2016

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

@HugeTimor
Copy link
Author

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?

@zsurocking
Copy link
Contributor

It will create a new transport and a new connection. And yes, it has performance overhead.
I don't think we have any plans yet. It's not likely this quarter though.

A quick workaround might be monitoring the network yourself and starts a new channel when wifi connects.

@HugeTimor
Copy link
Author

Thanks your help .

@ejona86 ejona86 changed the title A multiplexed channel do`t reconnect immediately when network unavailable long time then turn available. Provide hook for network availability notification on Android Aug 23, 2016
@ejona86 ejona86 added this to the Next milestone Aug 23, 2016
@ericgribkoff ericgribkoff self-assigned this Aug 3, 2017
@bubenheimer
Copy link

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.

@ericgribkoff
Copy link
Contributor

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.

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?

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.

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.

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.

@bubenheimer
Copy link

bubenheimer commented Aug 9, 2017

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.

@bubenheimer
Copy link

bubenheimer commented Aug 11, 2017

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.

@kraghu
Copy link

kraghu commented Aug 29, 2017

@ericgribkoff @ejona86 any update on this ? We need some options here

@bubenheimer
Copy link

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.

@ericgribkoff
Copy link
Contributor

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.

@ejona86
Copy link
Member

ejona86 commented Nov 2, 2017

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.

@kraghu
Copy link

kraghu commented Nov 2, 2017

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 :(.
I dont wanna give up on this one too. It is not easy to restart the whole connection at the application level without a proper hook.

@bubenheimer
Copy link

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.

@ericgribkoff
Copy link
Contributor

Closing this, as the network availability hook landed in #3580 (resetConnectBackoff()). #3688 tracks the follow-up issue of smoothly switching networks for new RPCs, when cellular is switching to wifi.

@ejona86 ejona86 modified the milestones: Next, 1.8 Jan 25, 2018
@lock lock bot locked as resolved and limited conversation to collaborators Sep 28, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants