Распределенная синхронизация времени и веб-приложения

В настоящее время я пытаюсь создать приложение, которое по своей сути требует хорошей синхронизации времени на сервере и на каждом клиенте. Для моего приложения есть альтернативные конструкции, которые могут избавить от этой потребности в синхронизации, но мое приложение быстро начинает отстой, когда его нет.

Если мне чего-то не хватает, моя основная проблема заключается в следующем: запуск события в нескольких местах в один и тот же момент. Насколько я могу судить, единственный способ сделать это требует какой-то синхронизации времени, но я могу ошибаться. Я пробовал моделировать проблему по-другому, но все сводится к а) отстойному приложению или б) требующему синхронизации времени.

Предположим, мне действительно действительно нужно синхронизированное время.

Мое приложение построено на Google AppEngine. Хотя AppEngine не дает никаких гарантий относительно состояния синхронизации времени на своих серверах, обычно это неплохо, порядка нескольких секунд (т.е. лучше, чем NTP), однако иногда это плохо, скажем, порядка 10 секунд. синхронизации. Мое приложение может обрабатывать 2-3 секунды рассинхронизации, но о 10 секундах не может быть и речи с точки зрения взаимодействия с пользователем. В общем, выбранная мной серверная платформа не обеспечивает очень надежную концепцию времени.

Клиентская часть моего приложения написана на JavaScript. Опять же, у нас есть ситуация, когда клиент также не имеет надежного представления о времени. Я не проводил никаких измерений, но полностью ожидаю, что у некоторых из моих потенциальных пользователей будут компьютерные часы, настроенные на 1901, 1970, 2024 и так далее. В общем, моя клиентская платформа не дает надежного представления о времени.

Эта проблема начинает меня немного бесить. Пока что лучшее, что я могу придумать, - это реализовать что-то вроде NTP поверх HTTP (это не так безумно, как может показаться). Это будет работать путем ввода в эксплуатацию 2 или 3 серверов в разных частях Интернета и использования традиционных средств (PTP, NTP), чтобы попытаться обеспечить их синхронизацию, по крайней мере, порядка сотен миллисекунд.

Затем я бы создал класс JavaScript, который реализовал алгоритм пересечения NTP, используя эти источники времени HTTP (и связанную информацию о двустороннем обращении, доступную из XMLHTTPRequest).

Как видите, это решение тоже отстой. Это не только ужасно сложно, но и решает только половину проблемы, а именно дает клиентам хорошее представление о текущем времени. Затем я должен пойти на компромисс на сервере, либо разрешив клиентам сообщать серверу текущее время в соответствии с ними, когда они делают запрос (большая безопасность нет-нет, но я могу смягчить некоторые из наиболее очевидных злоупотреблений этим), или заставить сервер сделать один запрос к одному из моих волшебных серверов HTTP-over-NTP и надеяться, что этот запрос завершится достаточно быстро.

Все эти решения - отстой, и я потерялся.

Напоминание: я хочу, чтобы несколько веб-браузеров, надеюсь, их было 100 или больше, могли запускать событие в одно и то же время.


person dmw    schedule 11.01.2009    source источник


Ответы (5)


Мне кажется, что вам нужно прослушивать широковещательное событие с сервера во многих разных местах. Поскольку вы можете принять 2-3-секундные вариации, вы можете просто поместить всех своих клиентов в долгоживущие запросы в стиле комет и просто получить ответ от сервера? Мне кажется, клиентам не нужно было бы иметь дело со временем таким образом?

Для этого вы можете использовать ajax, чтобы избежать блокировок на стороне клиента при ожидании новых данных.

Возможно, я здесь чего-то полностью упускаю.

person krosenvold    schedule 11.01.2009

Позвольте мне подвести итог, чтобы убедиться, что я понял вопрос.

У вас есть приложение, в котором есть клиентский и серверный компоненты. Существует несколько серверов, каждый из которых может обслуживать множество (сотни) клиентов. Серверы более или менее синхронизированы друг с другом; клиентов нет. Вы хотите, чтобы большое количество клиентов выполняло одно и то же событие примерно в одно и то же время, независимо от того, к какому серверу они подключились изначально.

Если предположить, что я более-менее точно описал ситуацию:

Можете ли вы сделать так, чтобы серверы сохраняли определенное состояние для каждого клиента (например, начальное время соединения - время сервера), и когда известно время события, которое должно произойти, уведомить клиента сообщением, содержащим количество миллисекунд после начального значения, которое должно пройти до запуска события?

Проиллюстрировать:

   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}

Это вообще не зависит от времени клиента; просто от способности клиента отслеживать время в течение некоторого достаточно короткого периода (один сеанс).

person SquareCog    schedule 11.01.2009

Синхронизацию времени очень сложно сделать правильно, и, на мой взгляд, это неправильный способ. Вам нужна система событий, которая может уведомлять зарегистрированных наблюдателей каждый раз при отправке события (шаблон наблюдателя) . Все наблюдатели будут уведомлены одновременно (или как можно ближе к этому), что устраняет необходимость в синхронизации времени.

Чтобы учесть задержку, браузеру должна быть отправлена ​​метка времени отправки события, и он должен ждать немного дольше, чем вы ожидаете максимальной задержки. Таким образом, все события будут запускаться одновременно во всех браузерах.

person Eran Galperin    schedule 11.01.2009
comment
Привет, Эран! Переход к системе событий только переносит проблему времени в другое место, а именно в сеть. Я могу использовать долгоживущие HTTP-запросы, срок действия которых истекает в нужный момент, но они будут иметь переменные задержки в зависимости от того, как далеко HTTP-клиент находится от сервера. - person dmw; 11.01.2009
comment
Нет, система событий не основана на времени - все наблюдатели уведомляются независимо от времени события. Если вам известно о задержке, создайте событие с периодом ожидания с максимальной ожидаемой задержкой и попросите браузер вычислить, сколько времени осталось от периода ожидания. - person Eran Galperin; 11.01.2009

Если вы можете предположить, что часы достаточно стабильны, то есть они установлены неправильно, но тикают с более или менее правильной скоростью.

Пусть серверы получают свое смещение из одного определенного источника (например, одного из ваших серверов, или сервера базы данных, или чего-то еще).

Затем попросите каждого клиента вычислить его смещение от своего сервера (возможные сложности с двусторонним обменом, если вам нужна большая точность).

Сохраните это, а затем вы объедините смещение для каждого клиента, чтобы вызвать событие в нужное время.

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

Google нашел способ определить время как абсолютное. Это звучит еретично для физика и по отношению к общей теории относительности: время течет с разной скоростью в зависимости от вашего положения в пространстве и времени, на Земле, во Вселенной ...

Вы можете ознакомиться с базой данных Google Spanner: http://en.wikipedia.org/wiki/Spanner_(database)

Я предполагаю, что сейчас он используется Google и будет доступен через Google Cloud Platform.

person Derek    schedule 28.03.2014