Skip to content
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

Websocket keepalive #21

Closed
ThraaxSession opened this issue Aug 2, 2017 · 5 comments
Closed

Websocket keepalive #21

ThraaxSession opened this issue Aug 2, 2017 · 5 comments

Comments

@ThraaxSession
Copy link

Hi :)

it's a nice framework. But I've got a little issue with the connection timeout on websocket.

[70294c19-6a40-4f0e-93a2-84ef22679498] onError: Timeout on Read
[70294c19-6a40-4f0e-93a2-84ef22679498] onClose: 1001 Idle Timeout

Do you know how to do a keepalive on websocket? Didn't find anything on Jetty side.
Or how to do a ping/pong at least. (With JS side)

Thanks and best regards
Gino

@danneu
Copy link
Owner

danneu commented Aug 5, 2017

Thanks.

I was thinking of removing the websocket stuff to minimize the feature set for a 1.0 release, so I've neglected that bit of kog. My implementation is kinda awkward so that websocket routes could be mounted behind other kog middleware, which is a feature I want to keep after finding a better impl.

I'll look into it because I'm curious as well now.

@danneu
Copy link
Owner

danneu commented Aug 6, 2017

@GinoHereIam Oh, you can set kog's idle timeout when constructing the server.

import com.danneu.kog.Server
import java.time.Duration

fun main(args: Array<String>) {
    Server(handler, idleTimeout = Duration.ofMinutes(5)).listen(3000)
}

kog passes it through to Jetty. Jetty (and thus kog) defaults to 30 seconds.

Edit: Let me test that this actually works.

@danneu
Copy link
Owner

danneu commented Aug 6, 2017

Alright, it works, but after some quick tests, Jetty seems to only support a max idle timeout of 5 minutes. Passing in a duration over 5 minutes seems to result in an idle timeout of 5 minutes, no more.

Also, reverse proxies like nginx or Heroku's load balancer or Cloudflare often have their own idle timeouts which may be shorter than kog's. IIRC Heroku will timeout idle connects after 30 seconds (which is Jetty's default). So even if kog has an idle timeout of 5 minutes, Heroku would terminate connections long before that.

I think this is one of the reasons why websocket libraries like https://socket.io/ implement their own ping/pong -- to avoid idle timeout.

I'll update the websockets section of the readme.

Thanks for being a guinea pig and bringing this issue up! 😄

So I'm pretty sure you have to make your clients ping the server to keep connections alive. Heroku confirms: https://devcenter.heroku.com/articles/websockets#timeouts

@danneu
Copy link
Owner

danneu commented Aug 6, 2017

@danneu danneu closed this as completed Aug 6, 2017
@ThraaxSession
Copy link
Author

Hi @danneu :)
sorry for late reply, I am busy now.

I solved this issuse with this little piece of code :D

session.idleTimeout = 0

Here a bit more code to clarify the location in code:

        // This endpoint will open a websocket connection that echos back any text the client sends it.
        get("/ws/test", fun(): Handler = {
            // Current limitation: The first argument to Response.websocket() must be a static url path.
            // It does *not* accept route patterns like "/ws/<num>". (#willfix)
            Response.websocket("/ws/test", fun(_: Request, session: Session): WebSocketHandler {
                // Upon each websocket connection at this endpoint, generate a random id for it
                val id = java.util.UUID.randomUUID()
                println("Started websocket connection ${DateTime.now().toLocalDateTime()}")

                // hopefully this is unlimited
                // the connection should never be closed!
                session.idleTimeout = 0

                return object : WebSocketHandler {
                    override fun onOpen() {
                        println("[$id] a client connected")
                    }
                 ...

I do this at the begin of the websocket connection. After setting the idleTimeout to 0, the connection stays alive. Without any ping/pong implementation. (For luck) :D

I hope this helps you.
And please don't remove it. :O I like it.

Best regards
Gino

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants