close() method when using streaming protocols

812 views
Skip to first unread message

Chris

unread,
Feb 22, 2013, 7:13:54 PM2/22/13
to soc...@googlegroups.com

Just would like to confirm this: when using streaming protocols (xhr or xdr), when a client calls conn.close() programmatically, will the connection be immediately terminated (in other words, on_close() method on both server and client side is triggered), regardless the state of the underlying network connection?

more specifically, i'm doing sth like this in the client:

function go() {
    disconnect();
    nextUrl = "https://www.example.com/blah/blah/"; // this is on the same domain
    window.location.replace(nextUrl);
}

function disconnect() {
    if (conn != null) {
        window.console && console.log('Client - Disconnecting...');
        conn.close();
        conn = null;
        window.console && console.log('Client - Disconnected');
    }
}

so whenever 'go()' is called, it will explicitly disconnect (on client side) and move on to the another page (within the same domain). For websocket-based clients, calling 'conn.close()' immediately terminate the session, and on_close() method on the server side is triggered.

however, I have seen during the tests that, when using streaming protocols, calling conn.close() does NOT cause on_close() method being invoked on the server side instantly. In fact, even after the user has got through a few different pages without sockjs on the same domain, the sockjs server thinks the client is still connected.

Is this expected behavior for streaming protocols in sockjs?


Chris

unread,
Feb 25, 2013, 4:34:05 PM2/25/13
to soc...@googlegroups.com

Just found this: https://github.com/sockjs/sockjs-client/issues/37, which may be relevant. I have to add that my environment is OS X 10.6.8 with no AVAST installed, yet this happened in the latest Chrome for me.

Certainly this kind of behavior is undesirable, but I wonder whether it is avoidable. Thanks.

heinob

unread,
Feb 26, 2013, 2:21:36 AM2/26/13
to soc...@googlegroups.com
Calling close() on the client with streaming protocols does immediately invoke 'close' on the server on my side. I have tested it with IE9 and xhr_streaming!

Chris

unread,
Feb 26, 2013, 8:35:41 PM2/26/13
to soc...@googlegroups.com

Did you test this on localhost with nothing between IE9 and the sockjs server? And how much communication is there between the client and the server before you calling close()?

I've just done a good number of tests today, with servers hosted on linode sitting behind HAProxy. I can re-produce this problem with IE9 every single time, after sending and receiving msgs for about 5 mins. Meanwhile, clients using websocket function as expected.

heinob

unread,
Feb 27, 2013, 11:34:06 AM2/27/13
to soc...@googlegroups.com
Hhhhmmmm. My sockjs-server (nodejs) is not on localhost. It is a different computer connected via cisco vpn. There was not much traffic before calling close. To be honest only the connect. 

Marek Majkowski

unread,
Feb 28, 2013, 11:39:27 PM2/28/13
to bhp...@gmail.com, soc...@googlegroups.com
On Tue, Feb 26, 2013 at 8:35 PM, Chris <bhp...@gmail.com> wrote:
>
> Did you test this on localhost with nothing between IE9 and the sockjs
> server? And how much communication is there between the client and the
> server before you calling close()?
>
> I've just done a good number of tests today, with servers hosted on linode
> sitting behind HAProxy. I can re-produce this problem with IE9 every single
> time, after sending and receiving msgs for about 5 mins. Meanwhile, clients
> using websocket function as expected.

Interesting.

In theory it is possible that there is a bug in sockjs and XHR/XDR
requests aren't
aborted on page refresh. It's quite common for IE to leak memory.
On the other hand code that does explicitly xhr.abort() on onunload event.

Can you reproduce this on localhost? You can try installing haproxy
on localhost.

Cheers,
Marek

Chris

unread,
Mar 1, 2013, 3:56:17 PM3/1/13
to soc...@googlegroups.com, bhp...@gmail.com

The problem is that, even if I explicitly call conn.close() before leaving the page, xhr-streaming simply just won't break the connection. Eventually, it will be timed out because of timeout limit set on HAProxy.

In fact, I have seen the same problem even with Chrome when it's using xhr-streaming instead of websocket, so this is probably not just an IE bug. It probably has more to do with xhr-streaming in sockjs itself.

I am fairly confident in terms of reproducing this problem, at least on linode. I've tried the same HAProxy version and setup on a different linode server this afternoon, and the problem persists. If it helps, I can send you the haproxy config for further diagnosis.

Marek Majkowski

unread,
Mar 1, 2013, 6:22:54 PM3/1/13
to bhp...@gmail.com, soc...@googlegroups.com
On Fri, Mar 1, 2013 at 3:56 PM, Chris <bhp...@gmail.com> wrote:
> The problem is that, even if I explicitly call conn.close() before leaving
> the page, xhr-streaming simply just won't break the connection. Eventually,
> it will be timed out because of timeout limit set on HAProxy.
>
> In fact, I have seen the same problem even with Chrome when it's using
> xhr-streaming instead of websocket, so this is probably not just an IE bug.
> It probably has more to do with xhr-streaming in sockjs itself.
>
> I am fairly confident in terms of reproducing this problem, at least on
> linode. I've tried the same HAProxy version and setup on a different linode
> server this afternoon, and the problem persists. If it helps, I can send you
> the haproxy config for further diagnosis.

Sorry to say, but and I am fairly confident that the problem is somehow specific
to you. Here you have a test for the "onclose" handler on the server side:
https://github.com/sockjs/sockjs-client/blob/master/tests/html/src/tests.coffee#L242-L259

You can run it online:
https://sockjs.popcnt.org/tests-qunit.html?filter=xhr-streaming%3A%20user%20close

Works for me.

I'd be interested to see if you could show me how to reproduce the
problem on a local machine.

Marek

hasher

unread,
Mar 4, 2013, 11:40:32 AM3/4/13
to soc...@googlegroups.com
I noticed that sometimes when user leaves my page, server does not notice it immediately, only after some long time.

Marek Majkowski

unread,
Mar 4, 2013, 11:46:12 AM3/4/13
to krzyszc...@gmail.com, soc...@googlegroups.com
On Mon, Mar 4, 2013 at 11:40 AM, hasher <krzyszc...@gmail.com> wrote:
> I noticed that sometimes when user leaves my page, server does not notice it
> immediately, only after some long time.

This is a very helpful comment. Thank you for contributing to the discussion.

Marek

hasher

unread,
Mar 4, 2013, 11:53:00 AM3/4/13
to soc...@googlegroups.com, krzyszc...@gmail.com
Okay.. I've add some code to check what transport these users use, will post about it soon.

Chris

unread,
Mar 5, 2013, 10:15:15 AM3/5/13
to soc...@googlegroups.com, krzyszc...@gmail.com

Exactly the same thing I observe on my side too. Such connections just time out in the end, and eventually invoke on_close on the server side.

I suspect that you will find one of the non-websocket protocols, and if you allow streaming ones, it'll likely be those.

Which sockjs server are you using and which reverse proxy do you use in front of it?

Chris

unread,
May 14, 2013, 11:11:28 PM5/14/13
to soc...@googlegroups.com, bhp...@gmail.com

Hi marek,

I'd be interested to see if you could show me how to reproduce the problem on a local machine.

Sorry for bringing back life an old question/problem. As per your comment above, I've finally got around to try it on a local machine (OS X 10.6.8). So I installed the lastest HAProxy 1.5-dev18 and the latest sockjs-tornado, and wrote the simplest server and client to demonstrate the reported problem (which is, for streaming protocol, the on_close() in sockjs-tornado will not be invoked until the timeout on HAProxy is reached, even if the client explicitly disconnects earlier).

The result: the same problem also happens on local machine. In addition, I've found that the 'timeout server xxx' option in HAProxy controls the length of streaming connections. For example, if I set it to 'timeout server 300s', the sockjs-tornado server will close the connection after 300 secs regardless what the client does: if the client programmatically disconnects before 300 secs, on_close() will not be invoked on server until 300s passed; on the other hand, the client can't stay connected more than 300s due to the same timeout. You can change the setting to see its effect.

Here I attach the config and source files for the test. To run the test, look at the console tab of the developer tools view in your browser, and you will see the log messages which tell you the state the connection. At the same time, observe the print-out logging from the console where you run the sockjs-tornado server. You will see that, even after the client disconnects, the server will not be notified until the specified timeout limit on haproxy is reached. This problem does not seem to affect websocket connections. Please let me know if you could reproduce what i see and how can we fix it.

thanks a lot,
chris
haproxy.cfg
test_streaming_disconnection.py
test-streaming-disconnection.html

Serge S. Koval

unread,
May 15, 2013, 9:13:05 AM5/15/13
to bhp...@gmail.com, sockjs
Hi,

 I'm sockjs-tornado maintainer and will try to reproduce the issue.

 Did you try it with sockjs-node, by the way?

On Wed, May 15, 2013 at 6:11 AM, Chris <bhp...@gmail.com> wrote:
The result: the same problem also happens on local machine. In addition, I've found that the 'timeout server xxx' option in HAProxy controls the length of streaming connections. For example, if I set it to 'timeout server 300s', the sockjs-tornado server will close the connection after 300 secs regardless what the client does: if the client programmatically disconnects before 300 secs, on_close() will not be invoked on server until 300s passed; on the other hand, the client can't stay connected more than 300s due to the same timeout. You can change the setting to see its effect.
That's strange - haproxy should close proxied connection when client disconnects.
 
Also, can you confirm same behavior with any of the polling transports?

Serge.

Chris Yang

unread,
May 15, 2013, 10:10:32 AM5/15/13
to Serge S. Koval, sockjs
hi serge,

i have not tried sockjs-node, cuz i have very little experience with it. but i guess if the same problem happens, then it's not something unique to sockjs-tornado.

i just tried xhr-polling, and that worked with ie8 (inside vmware fusion on the same mac). calling conn.close() in client closes connection on both client and server. however, iframe-eventsource produces the same problem as xhr-streaming on chrome. also, in all cases, the onclose callback is correctly fired on the client, the problem is whether sockjs-tornado acknowledges the disconnection too. seems like haproxy knows the disconnection between the client and itself, but still maintains the connection between itself and the backend server for some reason, which makes sockjs-tornado thinks the connection is still there, until the timeout kicks in.

thank you for looking into this.

regards,
chris

Chris Yang

unread,
Jun 10, 2013, 10:09:48 AM6/10/13
to Serge S. Koval, sockjs
Hi Serge,

Just a quick update on this issue. I also tried the latest tornado 3.0.2, and it didn't work either. So I suspected it might to do with HAProxy.

As it turned out, i need to turn on option abortonclose (http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-option%20abortonclose) on haproxy to make it aware of disconnection by clients using streaming or eventsource.

I don't see any downside of having this option on when using sockjs-tornado, so I've adopted the change. Hope this helps. Thanks.



Regards,
Chris
Reply all
Reply to author
Forward
0 new messages