In one of my previous posts, I talked about different session types in LCDS (along with FlexClient that represents the SWF), and I tried to explain the relationship (or lack thereof) among them in terms of sharing session data. In this post, I want to talk about sessions again, but more about their relationship with the underlying connection, and also touch upon some configuration properties related to sessions and connections.
In RTMP, the FlexSession (more specially its subclass RTMPFlexSession) is directly tied to the underlying connection which means that if the connection is closed for whatever reason, the session gets invalidated. This can be done with RTMP because there’s a dedicated socket connection between the client and the server, and it’s the ideal situation because once the client/connection is gone, you want everything about the client cleaned up on the server sooner rather than later.
HTTP is not a duplex protocol, and there’s no dedicated socket connection between the client and the server. Therefore it’s harder to detect when the client is gone and invalidate the FlexSession (more specially NIOHTTPFlexSession subclass) on the server. In HTTP, session timeout configuration option is needed because of that and it’s what you can rely on to clean up the NIOHTTPFlexSession in the absence of any feedback from the client. The session timeout is defined as “session-timeout-minutes” in services-config.xml in LCDS.
Session timeout works fine in most applications, but if it’s set to something high, say 15 minutes, and the client is gone (say the user closes the browser window), it’ll take the server 15 minutes to invalidate the session. This can be problematic in some applications, so, LCDS has another configuration option called “invalidate-session-on-disconnect”. If enabled, when a disconnect message is received from a client, its corresponding server session will invalidate. The idea here is that before the client goes away, it can send a disconnect message to the server (eg.Consumer#disconnect or ChannelSet#disconnectAll), and the server will invalidate the session instead of waiting for session timeout. Similar to session-timeout-minutes, Invalidate-session-on-disconnect is only used with HTTP based channels/endpoints because RTMP channel/endpoint already invalidates the session when the client is gone as I just explained.
There’s another little but useful configuration option called “connection-idle-timeout-minutes” in LCDS. It is a NIO-server level config (i.e. applies to RTMP and HTTP endpoints) and specifies the number of minutes that a connection may remain idle before the server closes it. By idle, I mean no data is read or written over the connection. It is more useful in RTMP connections because only in RTMP, you have long-lived connections and hence the concern of idle connections. In HTTP, connections are opened and closed for each HTTP request/reply, so it’s less of a concern. Also, in RTMP, sessions are tied to the connections, so closing a connection effectively means invalidating a session but the same is not true for HTTP.
This covers regular RTMP and HTTP endpoints but life is a little more complicated with HTTP-streaming. In HTTP-streaming endpoints, there are 2 connections involved. One is the regular HTTP request/reply connection, and the other one is HTTP-chunked connection that remains open for server-to-client updates (which is kind of against the HTTP philosophy but that’s what the “Comet” people, including us, had to come up with in the absence of WebSockets). For the HTTP-chunked connection, you don’t want to keep this connection open if the client is gone for a number of reasons, and LCDS could actually detect whether the client is gone by writing heartbeat bytes over the open HTTP-chunked connection. That’s what “server-to-client-heartbeat-millis” config option is for. When it’s set, say 5 seconds, when the server did not send updates to the client in the last 5 seconds, it’ll send a single null byte to the client to see if it’s still there. If not, then it’ll close the HTTP-chunked connection. Note that this does not invalidate the HTTP session, it simply closes the HTTP-chunked connection, and at that point, the client needs to reopen the streaming connection.
Finally, there’s also a socket level setting called “socket-keepalive-enabled” in LCDS. When it’s enabled, it basically calls Socket#setKeepAlive method on the underlying socket connection, and what does this do? Well, this link explains it pretty good. This option is probably more useful with RTMP with its long lived connections and possibly with HTTP-streaming for the HTTP-chunked connection.
All of this so far has been to detect and clean up resources on the server, but what about the client? Doesn’t the client need to know about disconnects? Sure it does, and for that, LCDS has a property called “heartbeatInterval” in ChannelSet or “heartbeat-interval-millis” in the configuration. It’s similar to socket-keepalive-enabled conceptually but it’s from client to server rather than the other way around. Once it’s set, it sends periodic heartbeat messages to the server to keep the connection alive, and to detect loss of connectivity. This is especially useful for clients receiving server-to-client updates but not sending client-to-server updates that often.
This wraps up our discussion. All of this might sound complicated, but it’s not once you understand the basics. The perceived complexity is due to fact that LCDS supports multiple protocols, encodings, and different connectivity flavors within protocols in order to be the foundation for all sorts of applications, and the knobs are necessary evil in supporting the flexibility needed from LCDS.