Я ищу решение проблемы на моем облачном сервере, на котором результат возвращается из microtime (true); очень точна между звонками в течение нескольких минут друг от друга, но почти через секунду проходит через секунду. Я использую этот результат для синхронизации между асинхронно подключенными клиентами, и мне нужна точность, чтобы быть точным для NIST в течение <~ 10 мс или около того, если это вообще возможно.
Я знаю, что это можно считать вне темы, но самым лучшим вариантом, который я могу придумать, является регулярное опрос некоторых внешних сервисов и получение текущего времени NIST в миллисекундах. К сожалению, я не могу найти кого-либо, предлагающего эту услугу. Если мне нужно, я просто настрою второй сервер с надежным временем отклика и пингом, но похоже, что кто-то там должен решить эту простую задачу. Кто-нибудь знает что-то?
Я нашел следующую услугу:
http://currentmillis.com/api/millis-since-unix-epoch.php
Просто имейте в виду, для тех, кто ищет аналогичное решение, что сетевая латентность и общие непредсказуемые факторы, безусловно, перекосят возвращаемое значение от истинного времени. Вы должны учитывать эти эффекты во всем, что вы используете для этого!
Обновить:
После использования вышеуказанной услуги в течение нескольких дней стало ясно, что мне нужно немного больше надежности, чем это было возможно благодаря соединению, в котором он сейчас находится. Мое решение состояло в том, чтобы создать клиент на основе PHP, реализованный посредством прямого подключения сокета к соседнему NTP-серверу. Я получаю время кругового путешествия от примерно 7 до 15 мс при типичном вызове.
Ваши результаты могут отличаться в зависимости от вашего собственного сервера, а также от вашего выбора поставщика NTP. Здесь вы можете найти серверы stratum 2, а также использовать общий пул . Как упоминалось в этих других сообщениях, НЕ проводите постоянный опрос этих поставщиков, но дросселируйте свои звонки и настраивайте их в соответствии со временем вызова.
Вот мой код для «клиента»:
function RemoteNTP($Host) { $Sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); // Create socket socket_connect($Sock, $Host, 123); // Connect over port 123 for NTP $Str = "\010" . str_repeat("\0", 47); // Create string for binary transmission $Trip -= round(microtime(true)*1000); // Grab time of call socket_send($Sock, $Str, strlen($Str), 0); // Send transmission socket_recv($Sock, $Response, 48, MSG_WAITALL); // Receive formatted response $Trip += round(microtime(true)*1000); // Adjust call time variable socket_close($Sock); // Close socket $Data = unpack('N12', $Response); // Format as an array we can work from $Secs = $Data[11]-2208988800; // Convert to secs since 1970, from 1900 for NTP $Frac = $Data[12]/4294967296; // Fraction of sec, out of 2^32 (32 bits) $Time = ($Secs*1000)+round($Frac*1000); // Combine for full ms value $Time += round($Trip/2); // Measure and adjust this for better accuracy return $Time; // Returns number of milliseconds passed since 1970-01-01 }
Что можно назвать следующим:
$Ntp = GetRemoteNTP('0.pool.ntp.org');
Вы получите более точное время отключения, изменив модификатор $ Trip на основе текущих проверок, чтобы определить фактические значения времени выхода и времени для каждого вызова. (Я на самом деле отслеживаю мои детали, но хочу опубликовать это модульным способом и оставить выбор механизмов отслеживания открытым для исполнителя.) Вы повысите надежность, оттачивая на NTP-провайдере в непосредственной близости от вашего сервера, но если используя пул, вы также можете «объединить» свои вызовы на серверы пула, добавив 0-4 к URL-адресу хоста и циклическому циклу для каждого запроса.
Также имейте в виду, что это следует рассматривать как решение последнего типа. Структура NTP была тщательно разработана, чтобы быть надежной и всеобъемлющей системой для поддержания очень точного системного времени. Это низкоуровневый механизм самокорректировки, который будет выполнять гораздо лучшую работу, чем домашний взлом, подобный этому. Я прибегаю к методу, используемому здесь из-за моих конкретных обстоятельств; есть вероятная лучшая альтернатива, доступная вам в системных часах, с автоматической настройкой через nptd.
Если вы установите NTP на свой сервер, вы можете получить точность до 10 мс на своем сервере. Это зависит от сетевого расстояния между вашим сервером и вашей ссылкой и сетевой нагрузки на этом маршруте. Если вы сделаете HTTP-запрос какой-либо службы, вам повезет получить время в пределах 200 мс. Если вы хотите, чтобы ваши клиенты имели точное время с точностью до 10 мс, им понадобится NTP, а затем они смогут достичь цели. Локальная привязка GPS будет единственным надежным способом для этой точности.
Высокоточная синхронизация часов будет проблематичной, особенно в виртуализованной среде. Это точный случай для рекомендации не запускать контроллеры домена Kerberos / Windows в виртуальной среде, учитывая их тенденцию к высокому дрейфу часов.
Тем не менее, правильный ответ, разумеется, не для того, чтобы спам NIST в любой форме, поскольку они предоставляют услуги NTP в качестве вежливости и, безусловно, заблокируют вас за чрезмерные запросы.
Что вам нужно сделать, это спросить своего интернет-провайдера, если у них есть сервер NTP, который вы можете использовать для агрессивной синхронизации ваших часов, в идеале, с сервером 1 или 2, и укажите все ваши машины. Если нет, настройте свой собственный сервер stratum 2 [желательно по металу, а не виртуальный] и используйте его.
После того, как у вас есть подходящий сервер NTP, просто нужно настроить ntpd на частое обновление ваших часов с одного сервера, чтобы вы не дрейфовали больше, чем ограничение 10 мс.
Но на самом деле я не могу поколебать чувство, что необходимость столь сильной синхронизации этих разрозненных часов является симптомом плохого выбора дизайна. Можете ли вы не просто отправить эти «асинхронные клиенты» свою информацию о планировании, как «X микросекунды сейчас», а не полную метку времени в будущем?