Дрифт часов в Windows
Я разработал службу Windows, которая отслеживает бизнес-события. Он использует часы Windows для событий timestamp. Однако базовые часы могут резко дрейфовать (например, проигрывать несколько секунд в минуту), особенно когда CPU работают. Наши серверы используют службу времени Windows, чтобы оставаться в синхронизации с контроллерами домена, которая использует NTP под капотом, но частота синхронизации контролируется политикой домена, и в любом случае даже синхронизация каждую минуту по-прежнему допускает значительный дрейф. Существуют ли какие-либо методы, которые мы можем использовать для поддержания стабильности часов, кроме использования аппаратных часов?
Ответы
Ответ 1
Циклы часов должны быть предсказуемыми, но на большинстве аппаратных средств ПК - потому что они не предназначены для систем реального времени. Другие прерывания устройства ввода-вывода имеют приоритет перед прерыванием тактового сигнала, а некоторые драйверы выполняют обширную обработку в прерывании а не отложить его до отложенного вызова процедуры (DPC), что означает, что система не сможет обслуживать прерывание тактового сигнала до ( иногда) спустя долгое время после того, как оно было сигнализировано.
Другие факторы включают в себя контроллеры ввода-вывода с шиной, которые украшают многие циклы шины памяти из ЦП, в результате чего он задерживается в течение длительных периодов пропускной способности шины памяти.
Как говорили другие, аппаратура синхронизации часов также может изменять свою частоту по мере изменения значений компонентов с температурой.
Windows позволяет количество тиков, добавленных к часам реального времени, на каждом прерывании, которое нужно настроить: см. SetSystemTimeAdjustment. Однако это будет работать, только если у вас есть предсказуемое перекос часов. Если часы только немного отключены, SNTP-клиент (услуга "Время Windows" ) отрегулирует это перекос, чтобы сделать тактировку часов несколько быстрее или медленнее, чтобы двигаться в направлении правильного времени.
Ответ 2
Я не знаю, относится ли это, но...
В Windows возникает проблема: если вы измените разрешение таймера с timeBeginPeriod(), часы будут дрейфовать.
На самом деле, есть ошибка в реализации Java Thread wait()
(и os::sleep()
) Windows, которая вызывает это поведение. Он всегда устанавливает разрешение таймера на 1 мс перед ожиданием, чтобы быть точным (независимо от длины сна), и восстанавливает его сразу же после завершения, если только другие нити все еще не спят. Этот набор /reset будет затем путать часы Windows, который ожидает, что квант времени окна будет довольно постоянным.
Sun действительно известно об этом с 2006 года и не исправил его, AFAICT!
У нас на самом деле часы были в два раза быстрее из-за этого! Простая Java-программа, которая спит 1 миллисекунда в цикле, показывает это поведение.
Решение состоит в том, чтобы установить временное разрешение самостоятельно, на что-то низкое и сохранить его там как можно дольше. Используйте для этого время timeBeginPeriod(). (Мы устанавливаем его на 1 мс без каких-либо побочных эффектов.)
Для этих кодировок в Java более простой способ исправить это - создать поток, который спит, пока работает приложение.
Обратите внимание, что это устранит эту проблему на машине глобально, независимо от того, какое приложение является фактическим виновником.
Ответ 3
Вы можете запустить "w32tm/resync" в запланированном файле .bat задачи. Это работает на Windows Server 2003.
Ответ 4
Помимо повторной синхронизации часов чаще, я не думаю, что вы можете многое сделать, кроме как получить новую материнскую плату, так как ваш тактовый сигнал не кажется на правильной частоте.
Ответ 5
Как уже упоминалось, программы Java могут вызвать эту проблему.
Другим решением, которое не требует модификации кода, является добавление аргумента VM -XX:+ForceTimeHighResolution
(найдено на странице поддержки NTP).
9.2.3. Виртуальная машина Windows и Sun Java
Виртуальная машина Sun Java должна запускаться с параметром > -XX: + ForceTimeHighResolution, чтобы избежать потери прерываний.
Для получения дополнительной информации см. http://www.macromedia.com/support/coldfusion/ts/documents/createuuid_clock_speed.htm.
Из ссылочной ссылки (через Wayback machine - исходная ссылка ушла):
ColdFusion MX: CreateUUID Увеличивает скорость работы системы Windows
Вызов функции createUUID несколько раз при загрузке в Macromedia ColdFusion MX и выше могут привести к системным часам Windows ускоряться. Это проблема с виртуальной машиной Java (JVM) в который вызывает Thread.sleep менее 10 миллисекунд (мс), вызывает Системные часы Windows работают быстрее. Это поведение было первоначально подано как Sun Java Ошибка 4500388 (developer.java.sun.com/developer/bugParade/bugs/4500388.html) и имеет было подтверждено для JVM 1.3.x и 1.4.x.
В ColdFusion MX функция createUUID имеет внутренний Thread.sleep вызов 1 миллисекунды. Когда createUUID активно используется, Системные часы Windows получат несколько секунд в минуту. Скорость ускорение пропорционально количеству вызовов createUUID и загрузить на сервер ColdFusion MX. Macromedia наблюдала это поведение в ColdFusion MX и выше в Windows XP, 2000 и 2003 годах системы.
Ответ 6
http://www.codinghorror.com/blog/2007/01/keeping-time-on-the-pc.html
Часы ПК обычно должны быть точными с точностью до нескольких секунд в день. Если вы испытываете огромный дрейф часов - порядка минут в день - первое, что нужно проверить, это ваш источник питания переменного тока. Я лично наблюдал системы с ИБП, подключенными к другому ИБП (кстати, это нет-нет), которые набирали минуты в день. Извлечение ненужного ИБП из цепочки устраняет проблему времени. Я не инженер-аппаратчик, но я предполагаю, что какой-то сигнал синхронизации во власти используется чипом часов реального времени на материнской плате.
Ответ 7
Увеличьте частоту повторной синхронизации.
Если синхронизация выполняется с вашим собственным основным сервером в вашей собственной сети, нет никакой причины не синхронизировать каждую минуту.
Ответ 8
Синхронизировать чаще. Посмотрите Записи реестра для службы W32Time, особенно "Период". "SpecialSkew" звучит так, как будто это вам поможет.
Ответ 9
Дрейф часов может быть следствием температуры; может быть, вы могли бы попытаться получить температуру более постоянной - возможно, с использованием лучшего охлаждения? Однако вы никогда не потеряете дрейф.
Использование внешних часов (GPS-приемник и т.д.) и статистический метод для связывания времени процессора с Absolute Time - это то, что мы используем здесь для синхронизации событий в распределенных системах.
Ответ 10
Поскольку это звучит так, будто у вас большой бизнес:
Возьмите старый ноутбук или что-то, что плохо для многих, но, похоже, имеет более или менее надежные часы и назовите его Timekeeper. Задача Timekeeper - это, как только каждые (скажем) 2 минуты, отправить сообщение серверам, сообщающим время. Вместо того, чтобы использовать часы Windows для своих временных меток, серверы будут отключать время от последнего сигнала Timekeeper, а также прошедшее время с момента сигнала. Проверяйте часы Timekeeper своими наручными часами один или два раза в неделю. Этого должно быть достаточно.
Ответ 11
На каких серверах вы работаете? В десктопах, когда я сталкивался с этим, с включенным FSB с расширенным спектром, возникают некоторые проблемы с синхронизацией прерываний, что и делает тактику часов. Может захотеть проверить, является ли это вариант в BIOS на одном из этих серверов и отключить его, если он включен.
Другой вариант, который вы имеете, - отредактировать интервал опроса времени и сделать его намного короче, используя следующий раздел реестра, скорее всего, вам придется его добавить (обратите внимание, что это значение DWORD, а значение - в секундах, например, 600 на 10 мин):
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient\SpecialPollInterval
Здесь полная работа над этим: KB816042
Ответ 12
Я как-то написал класс Delphi для обработки временных пересинхронов. Он вставлен ниже. Теперь, когда я вижу команду "w32tm", упомянутую Ларри Сильверманом, я подозреваю, что потерял время.
unit TimeHandler;
interface
type
TTimeHandler = class
private
FServerName : widestring;
public
constructor Create(servername : widestring);
function RemoteSystemTime : TDateTime;
procedure SetLocalSystemTime(settotime : TDateTime);
end;
implementation
uses
Windows, SysUtils, Messages;
function NetRemoteTOD(ServerName :PWideChar; var buffer :pointer) : integer; stdcall; external 'netapi32.dll';
function NetApiBufferFree(buffer : Pointer) : integer; stdcall; external 'netapi32.dll';
type
//See MSDN documentation on the TIME_OF_DAY_INFO structure.
PTime_Of_Day_Info = ^TTime_Of_Day_Info;
TTime_Of_Day_Info = record
ElapsedDate : integer;
Milliseconds : integer;
Hours : integer;
Minutes : integer;
Seconds : integer;
HundredthsOfSeconds : integer;
TimeZone : LongInt;
TimeInterval : integer;
Day : integer;
Month : integer;
Year : integer;
DayOfWeek : integer;
end;
constructor TTimeHandler.Create(servername: widestring);
begin
inherited Create;
FServerName := servername;
end;
function TTimeHandler.RemoteSystemTime: TDateTime;
var
Buffer : pointer;
Rek : PTime_Of_Day_Info;
DateOnly, TimeOnly : TDateTime;
timezone : integer;
begin
//if the call is successful...
if 0 = NetRemoteTOD(PWideChar(FServerName),Buffer) then begin
//store the time of day info in our special buffer structure
Rek := PTime_Of_Day_Info(Buffer);
//windows time is in GMT, so we adjust for our current time zone
if Rek.TimeZone <> -1 then
timezone := Rek.TimeZone div 60
else
timezone := 0;
//decode the date from integers into TDateTimes
//assume zero milliseconds
try
DateOnly := EncodeDate(Rek.Year,Rek.Month,Rek.Day);
TimeOnly := EncodeTime(Rek.Hours,Rek.Minutes,Rek.Seconds,0);
except on e : exception do
raise Exception.Create(
'Date retrieved from server, but it was invalid!' +
#13#10 +
e.Message
);
end;
//translate the time into a TDateTime
//apply any time zone adjustment and return the result
Result := DateOnly + TimeOnly - (timezone / 24);
end //if call was successful
else begin
raise Exception.Create('Time retrieval failed from "'+FServerName+'"');
end;
//free the data structure we created
NetApiBufferFree(Buffer);
end;
procedure TTimeHandler.SetLocalSystemTime(settotime: TDateTime);
var
SystemTime : TSystemTime;
begin
DateTimeToSystemTime(settotime,SystemTime);
SetLocalTime(SystemTime);
//tell windows that the time changed
PostMessage(HWND_BROADCAST,WM_TIMECHANGE,0,0);
end;
end.
Ответ 13
Я считаю, что Windows Time Service реализует только SNTP, что является упрощенной версией NTP. Полная реализация NTP учитывает стабильность ваших часов при определении того, как часто синхронизировать.
Вы можете получить полный NTP-сервер для Windows здесь.