Feature Request: Offer More Flexible Websocket Pong Failure Policy
See original GitHub issueRight now, OkHttp’s websocket pong rule is: it must receive a pong for every ping, and that pong must be received before the time comes for the next ping (see #3227 and this code). I’m sure that works in many cases, but it is a fairly rigid policy. For example, right now I am dealing with an IoT device where I have to ping frequently, but I might not get pongs all the time.
At the moment, I am trying to work around this by:
-
Identify a websocket failure due to a missed pong, by the icky approach of examining the exception handed to
onFailure()
and seeing if it is aSocketTimeoutException
and hasdidn't receive pong
in the message -
Open a fresh websocket and hope the IoT device can deal (spoiler alert: it can’t deal all that well…)
The current implementation is fine as a default, but it would be useful if we could have an asymmetric policy, with the ping interval at least somewhat independent of the pong timeout period. In my case, it would be something like:
- Send pings every 2 seconds
- Fail only if we do not receive a pong within 40 seconds
(or something like that)
Right now, we are using another websocket library. We are able to implement what we need there because all the guts are exposed, so we can send extra ping frames. We have configured the library’s automatic ping logic to have a long period (e.g., 40 seconds) to prevent an early websocket failure due to a missed pong, with the extra ping frames satisfying the IoT device’s need for more frequent pings. I am trying to switch over to OkHttp, because we’re going to need some of what it offers (particularly in the SSL/TLS area) eventually.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:2
- Comments:9 (3 by maintainers)
Top GitHub Comments
It’s just our approach to building an API. There’s lots of low-level libraries for users who want exact control over every byte. OkHttp works closer to the application layer: you tell OkHttp what request to make and it mostly just figures out the rest. We similarly don’t offer knobs to select how our HTTP/2 flow control works, or how much data we buffer when streaming a request body.
You might argue that this is inefficient, but I think in aggregate it’s quite efficient. We can automatically make good decisions even as the context changes. For example, when we support web sockets over HTTP/2 it’ll make very little sense to do pings the websocket layer and not the connection layer.
So if you’re with me, even just a bit, I’d love your best ideas on what our built-in ping policy should be.
Hm. My aspirations here are to make the pings + pongs dynamic and based on the other activity on the web socket.
Perhaps something like “send a ping after 10 seconds of inactivity” instead of “send a ping every 10 seconds”, and backing off from 10 seconds to 30 to 60 to 120, so that a web socket that doesn’t get much use also doesn’t need many pings. In such cases we could probably adjust the pong timeout to be based on a fixed deadline (say 30 seconds in high-latency environments, and 2 seconds in low-latency ones) rather than on the transmission time of the next ping.