views:

551

answers:

4

Hi there,

I'm currently trying to build an application that inherently needs good time synchronization across the server and every client. There are alternative designs for my application that can do away with this need for synchronization, but my application quickly begins to suck when it's not present.

In case I am missing something, my basic problem is this: firing an event in multiple locations at exactly the same moment. As best I can tell, the only way of doing this requires some kind of time synchronization, but I may be wrong. I've tried modeling the problem differently, but it all comes back to either a) a sucky app, or b) requiring time synchronization.

Let's assume I Really Really Do Need synchronized time.

My application is built on Google AppEngine. While AppEngine makes no guarantees about the state of time synchronization across its servers, usually it is quite good, on the order of a few seconds (i.e. better than NTP), however sometimes it sucks badly, say, on the order of 10 seconds out of sync. My application can handle 2-3 seconds out of sync, but 10 seconds is out of the question with regards to user experience. So basically, my chosen server platform does not provide a very reliable concept of time.

The client part of my application is written in JavaScript. Again we have a situation where the client has no reliable concept of time either. I have done no measurements, but I fully expect some of my eventual users to have computer clocks that are set to 1901, 1970, 2024, and so on. So basically, my client platform does not provide a reliable concept of time.

This issue is starting to drive me a little mad. So far the best thing I can think to do is implement something like NTP on top of HTTP (this is not as crazy as it may sound). This would work by commissioning 2 or 3 servers in different parts of the Internet, and using traditional means (PTP, NTP) to try to ensure their sync is at least on the order of hundreds of milliseconds.

I'd then create a JavaScript class that implemented the NTP intersection algorithm using these HTTP time sources (and the associated roundtrip information that is available from XMLHTTPRequest).

As you can tell, this solution also sucks big time. Not only is it horribly complex, but only solves one half the problem, namely giving the clients a good notion of the current time. I then have to compromise on the server, either by allowing the clients to tell the server the current time according to them when they make a request (big security no-no, but I can mitigate some of the more obvious abuses of this), or having the server make a single request to one of my magic HTTP-over-NTP servers, and hoping that request completes speedily enough.

These solutions all suck, and I'm lost.

Reminder: I want a bunch of web browsers, hopefully as many as 100 or more, to be able to fire an event at exactly the same time.

+1  A: 

Time synchronization is very hard to get right and in my opinion the wrong way to go about it. You need an event system which can notify registered observers every time an event is dispatched (observer pattern). All observers will be notified simultaneously (or as close as possible to that), removing the need for time synchronization.

To accommodate latency, the browser should be sent the timestamp of the event dispatch, and it should wait a little longer than what you expect the maximum latency to be. This way all events will be fired up at the same time on all browsers.

Eran Galperin
Hi Eran,Moving to an event system only shifts the time issue to someplace else, namely the network. I can use long-lived HTTP requests that expire at just the right moment, but these will have variable latencies depending on how far the HTTP client is from the server.
David Wilson
No, an event system is not time based - all observers are notified regarldless of the time of the event. If you are aware of latency, then issue the event with a waiting period of the maximum latency you expect, and have the browser calculate how much time is left from the waiting period
Eran Galperin
+3  A: 

It seems to me like you're needing to listen to a broadcast event from a server in many different places. Since you can accept 2-3 seconds variation you could just put all your clients into long-lived comet-style requests and just get the response from the server? Sounds to me like the clients wouldn't need to deal with time at all this way ?

You could use ajax to do this, so yoǘ'd be avoiding any client-side lockups while waiting for new data.

I may be missing something totally here.

krosenvold
+1  A: 

Let me summarize, to make sure I understand the question.

You have an app that has a client and server component. There are multiple servers that can each be servicing many (hundreds) of clients. The servers are more or less synced with each other; the clients are not. You want a large number of clients to execute the same event at approximately the same time, regardless of which server happens to be the one they connected to initially.

Assuming that I described the situation more or less accurately:

Could you have the servers keep certain state for each client (such as initial time of connection -- server time), and when the time of the event that will need to happen is known, notify the client with a message containing the number of milliseconds after the beginning value that need to elapse before firing the event?

To illustrate:

   client A connects to server S at time t0 = 0
   client B connects to server S at time t1 = 120
   server S decides an event needs to happen at time t3 = 500
   server S sends a message to A:
   S->A : {eventName, 500}
   server S sends a message to B:
   S->B : {eventName, 380}

This does not rely on the client time at all; just on the client's ability to keep track of time for some reasonably short period (a single session).

SquareCog
A: 

If you can assume that the clocks are reasonable stable - that is they are set wrong, but ticking at more-or-less the right rate.

Have the servers get their offset from a single defined source (e.g. one of your servers, or a database server or something).

Then have each client calculate it's offset from it's server (possible round-trip complications if you want lots of accuracy).

Store that, then you the combined offset on each client to trigger the event at the right time.

(client-time-to-trigger-event) = (scheduled-time) + (client-to-server-difference) + (server-to-reference-difference)
Douglas Leeder