Subject: [hybi] Keepalive's multiple purposes, and different ways it's done

From: Jamie Lokier <[email-masked]>
Date: Fri, 5 Mar 2010 17:07:12 +0000

Ian Hickson wrote:
> On Mon, 1 Mar 2010, Dave Cridland wrote:
> > This behavioural flux, though, is an excellent argument for putting 
> > keepalive behaviour into the core, as the people designing the 
> > frameworks are likely to have good ideas of the defaults, and keepalive 
> > frequencies will need to be controlled per-deployment, typically, rather 
> > than per-application.
> 
> We could reserve a frame byte for control messages (server talking to the 
> browser rather than to the script), with the null message being put aside 
> for keep-alive purposes, if people think that would be especially useful. 
> I presume we would want the server in charge of sending keepalives rather 
> than the browser or the script?

Keepalives and timeouts (they go together) are used for three
equally critical things:

   - Keeping TCP open over NATs.

   - Detecting when the connection is broken at the server, so you can
     clean it up instead of running out of memory and crashing the
     server after a few days.  (The Tic-Tac-Toe demo has this problem;
     as did some 1990's era HTTP servers.)

   - Detecting when the connection is broken at the client, so it
     can initiated another one.  (Interactive applications need this.)

To achieve all three, it's necessary to have keepalive messages sent
from both sides.  It is not enough to send a message from one side,
and rely on the TCP ACK coming back.  That'll keep the NAT open, but
it won't allow both sides to detect broken connection in a useful time.

This can be done as a "ping" style request+response, or each side can
transmit independently when it's not transmitted anything for a
keepalive interval - which I'll call "independent" style.

Assume a given NAT timeout, which we must stay below.

The "ping" style uses more bandwidth than the "independent" style if
the client and server's broken-connection timeouts are quite
different.  This is because you must reduce the keepalive interval by
more due to the extra round-trip jitter, and because it causes a
message in both directions resulting in 3 TCP packets, when 2 packets
would be enough most of the time due to asymmetric timeout
requirements.

However, When the server and client's broken-connection timeout needs
are the same, then the "ping" style uses less bandwidth than
"independent" style due to TCP piggybacking.  (It's possible to make a
hybrid which combines both depending on the timeout calculations, by
the way.)

Note that applications like, say, Facebook and Gmail would be better
off with asymmetric broken-connection timeouts and therefore using the
"independent" style.

In some applications, keepalive bandwidth is actually the main
bandwidth consumer!  Those are applications which need to maintain a
client-initiated connection to receive occasional messages, but don't
receive them often.  The financial cost of keepalives relative to
actual data can get quite expensive in those applications, so
minimising it is quite desirable.  (That's why I studied the issue to
come to the above observations about timeouts.)  And of course, the
effect on a busy link.

What I conclude from this is that each application must be able to
decide for itself what keepalive strategy it's going to use, and it
must not be assumed that server-initiated pings, or client-initiated
pings, are always a good choice.

-- Jamie