2

Working on a GAE project and one requirement we have is that we want to in a timely manner be able to determine if a user has left the application. Currently we have this working, but is unreliable so I am researching alternatives.

The way we do this now is we have a function setup to run in JS on an interval that sends a heartbeat signal to the GAE app using an AJAX call. This works relatively well, but is generating a lot of traffic and CPU usage. If we don't hear a heartbeat from a client for several minutes, we determine they have left the application. We also have the unload function wired up to send a part message, again through an AJAX call. This works less then well, but most of the time not at all.

We are also making use of the Channels API. One thing I have noticed is that our app when using an open channel, the client seems to also be sending a heartbeat signal in the form of a call to http://talkgadget.google.com/talkgadget/dch/bind. I believe this is happening from the iFrame and/or JS that gets loaded when opening channel in the client.

My question is, can my app on the server side some how hook in to these calls to http://talkgadget.google.com/talkgadget/dch/bind and use this as the heartbeat signal? Is there a better way to detect if a client is still connected even if they aren't actively doing anything in the client?

Dude0001
  • 3,019
  • 2
  • 23
  • 38
  • How many channels do you have open at once? How quickly do you need to know that someone has left? How often are you sending messages to clients? – Calvin Mar 23 '11 at 22:07
  • Oh, and are the clients usually silent, or do they communicate anything to the server other than the heartbeat (i.e. chat messages)? – Calvin Mar 23 '11 at 22:17
  • Each client holds open a single channel. Right now the number of concurrent users is small, but lets say we will shoot for 100 or more clients. The clients do send some messages to the server, but there is no guaranteeing the frequency. – Dude0001 Mar 23 '11 at 22:35
  • Also, I guess I'm more curious at this point if our app can some how "hook" into or otherwise detect on the server side these calls to the talkgadget bind function or some other documentation of this mechanism. – Dude0001 Mar 23 '11 at 22:39
  • The App Engine team is promising to add a presence feature that will notify you when a channel is closed by the client, but at the moment there's no way to hook into the talkgadget. But Moishe is the expert, maybe he'll comment on this question. – Calvin Mar 23 '11 at 22:48
  • I saw Moishe's comment about working on the presence feature in his comments on his answer to this question http://stackoverflow.com/questions/4804129/appengine-channel-api-best-way-to-check-if-a-channel-is-still-open-server-side This looks about like what we are looking for. – Dude0001 Mar 24 '11 at 00:00

4 Answers4

3

Google have added this feature:

See https://developers.google.com/appengine/docs/java/channel/overview

Tracking Client Connections and Disconnections

Applications may register to be notified when a client connects to or disconnects from a channel.

You can enable this inbound service in appengine-web.xml:

awmross
  • 3,789
  • 3
  • 38
  • 51
1

Currently the channel API bills you up-front for all the CPU time the channel will consume for two hours, so it's probably cheaper to send messages to a dead channel than to send a bunch of heartbeat messages to the server.

https://groups.google.com/d/msg/google-appengine/sfPTgfbLR0M/yctHe4uU824J

What I would try is attach a "please acknowledge" parameter to every Nth message (staggered to avoid every client acknowledging a single message). If 2 of these are ignored mute the channel until you hear from that client.

Calvin
  • 4,177
  • 1
  • 16
  • 17
1

You can't currently use the Channel API to determine if a user is still online or not. Your best option for now depends on how important it is to know as soon as a user goes offline.

If you simply want to know they're offline so you can stop sending messages, or it's otherwise not vital you know immediately, you can simply piggyback pings on regular interactions. Whenever you send the client an update and you haven't heard anything from them in a while, tag the message with a 'ping request', and have the client send an HTTP ping whenever it gets such a tagged message. This way, you'll know they're gone shortly after you send them a message. You're also not imposing a lot of extra overhead, as they only need to send explicit pings if you're not hearing anything else from them.

If you expect long periods of inactivity and it's important to know promptly when they go offline, you'll have to have them send pings on a schedule, as you suggested. You can still use the trick of piggybacking pings on other requests to minimize them, and you should set the interval between pings as long as you can manage, to reduce load.

Nick Johnson
  • 100,655
  • 16
  • 128
  • 198
1

I do not have a good solution to your core problem of "hooking" the client to server. But I do have an interesting thought on your current problem of "traffic and CPU usage" for periodic pings.

I assume you have a predefined heart-beat interval time, say 1 min. So, if there are 120 clients, your server would process heart beats at an average rate of 2 per second. Not good if half of them are "idle clients".

Lets assume a client is idle for 15 minutes already. Does this client browser still need to send heart-beats at the constant pre-defined interval of 1 min?? Why not make it variable?

My proposal is simple: Vary the heart-beats depending on activity levels of client.

When the client is "active", heart-beats work at 1 per minute. When the client is "inactive" for more than 5 minutes, heart-beat rate slows down to 50% (one after every 2 minutes). Another 10 minutes, and heart-beat rate goes down another 50% (1 after every 4 minutes)... At some threshold point, consider the client as "unhooked".

In this method, "idle clients" would not be troubling the server with frequent heartbeats, allowing your app server to focus on "active clients".

Its a lot of javascript to do, but probably worth if you are having trouble with traffic and CPU usage :-)

Mani
  • 23,635
  • 6
  • 67
  • 54