Windows的时刻同步(w32time)与业务系统 ── 从原理出发解决「日志时间戳对不上」的问题

· · w32time, NTP, 时刻同步, Windows, 日志, 故障排查, 设备联动, Active Directory

「设备异常停机了。把设备端的日志和 PC 端的应用日志对照后发现,时间相差了 40 秒,无法确定究竟是设备报错在先,还是应用通信中断在先」── 这是我们在设备联动系统的故障排查中反复遇到的场景。网络摄像机、PLC、检测设备,还有 Windows PC,各自按自己的时钟记录日志,而「这些时钟是否一致」这件事,其实从来没有人保证过。

平时几乎没有人会注意到时刻偏差。真正让人为难的,往往是在故障排查的时候,也就是需要把「事件的先后关系」作为证据的时候。而一旦开始调查,「工作组里的 PC 每周才同步一次」「虚拟机同时从主机和 NTP 两边获取时刻,来回摇摆」「设备的时钟原本就没有人校准过」这类事实就会接连浮现出来。

本文面向曾在设备与 PC、服务器与终端之间的日志比对上吃过苦头的开发者与信息系统负责人,基于 Microsoft 的一手资料,系统梳理 Windows 时刻同步服务(w32time)的运行原理、用 w32tm 命令诊断的实务做法、精度的现实预期,以及在「时刻会偏移、也会倒退」这一前提下业务系统一侧应有的设计。

1. 先说结论

  • Windows 的时刻由 Windows 时间服务(w32time)管理。它并非严格意义上的 NTP 实现,但属于使用 NTP 规范中的算法组来调整时钟的 NTP 客户端/服务器,通信使用 UDP 123 端口。1
  • 域环境中存在固定的时刻层级结构。成员与 DC 同步,DC 与父域的 DC 同步,层级的顶端是林根域的 PDC 模拟器。如果顶端没有与外部准确的时刻源同步,整个域就会一起出错。1
  • 工作组(非域)机器默认与 time.windows.com 进行低频同步。注册表默认的 SpecialPollInterval 在独立(standalone)配置下为 604,800 秒(1 周)。出现数十秒的偏差,是「按规格运行」的正常结果。23
  • 诊断只需一套 w32tm 命令就够了。w32tm /query /status 查看同步状态与同步源,用 /stripchart 实测与对方的时刻差,用 /config /manualpeerlist 指定同步目标,用 /resync 立即重新同步。2
  • w32time 对小幅偏差通过升降时钟走速逐步校准(平滑调整,slew),对大幅偏差则直接改写时钟(阶跃调整,step)。也就是说,系统时钟既可能向前跳,也可能向后跳。偏差一旦超过上限(MaxPos/MaxNegPhaseCorrection),就不会被校正,而只会记录到事件日志中──这一行为同样值得留意。12
  • 默认设置的精度目标历来只是「满足 Kerberos 的 5 分钟限制」这一程度。Windows Server 2016/Windows 10 1607 之后有了大幅改进,只要满足准确的 Stratum 1 时刻源、网络延迟、跳数等条件,1 秒/50 毫秒/1 毫秒的精度就被纳入了支持范围。4
  • Hyper-V 来宾机拥有主机和 NTP 两个时刻提供程序。Windows Server 2016 之后改进为由来宾机自动选择最优的一方,但对于 2012 R2 及更早版本、已加入域的来宾机,则建议禁用 Hyper-V 时刻同步提供程序。3
  • 应用一侧要以「时刻会偏移、也会倒退」为前提进行设计。日志时刻以 UTC 记录,经过时间的测量则使用与系统时钟无关、单调递增的 Stopwatch。这种分工是整个设计的基础。56

2. w32time 的运行原理 ── 域与工作组的行为截然不同

Windows 时间服务(W32Time)是 Windows 标准的时刻同步组件。它通过 NTP(以及面向域的安全协议 MS-SNTP)从网络上的时刻源获取时刻样本,用 NTP 的时钟过滤器/时钟选择算法挑出最优样本,据此调整本地时钟。1

需要牢记的是,同步目标的决定方式会因配置而截然不同

域环境(Type=NT5DS)中,AD DS 林预先设定好了固定的时刻层级结构。成员 PC/服务器与自身所在域的 DC 同步,DC 与父域的 DC 同步,层级的顶端是林根域的 PDC 模拟器(或被配置为可信时刻源的 DC)。NTP 数据包会用 Kerberos 会话密钥签名,只有经过认证的时刻才会被接受。1 因此,域内各 PC 之间通常能对得比较齐。问题出在顶端:如果 PDC 模拟器没有与外部准确的时刻源(GPS 时钟或可信的 NTP 服务器)同步,就会出现「所有人一起对齐到一个错误的时刻」的情况。而这种偏差,往往是在把日志与公司外部系统或云端记录进行比对的那一刻才暴露出来。

这里由管理员设置外部准确的时刻源GPS 时钟 / 可信的 NTP 服务器林根域的PDC 模拟器子域的 DC同一域内的其他 DC成员服务器 / PC成员服务器 / PC成员服务器 / PC

图 1:域的时刻层级结构 ── 箭头表示时刻分发的方向

把这棵树画成一张图就能清楚看到,只要根节点出错,所有人就会以同样的偏差一起出错。而且由于所有人都错得一致,只要还在比对公司内部的日志,就没有人会发现。直到与外部记录比对的那一天,才会第一次暴露出来。这正是应该最先检查顶端设置的原因。

工作组环境(Type=NTP)中,默认的同步目标是 time.windows.com,0x10x1(SpecialInterval)是一个由 SpecialPollInterval 注册表值决定轮询间隔的标志,其默认值在独立配置下为604,800 秒 = 1 周2 即便是 Windows 10 客户端,同步频率也不过大约每天一次,而 Windows Server 2012 R2 那一代的默认值则是每周一次。3 PC 内置时钟(晶体振荡器)受温度等环境因素影响、每天出现秒级漂移并不罕见,因此在每周同步一次的情况下,出现数十秒的偏差是很平常的事。开头提到的「相差 40 秒」,真相多半就是这个。

另一个在实务中十分重要的,是时钟规律(clock discipline)的行为方式。当偏差还小时,w32time 会通过升降时钟走速来逐步校准(平滑调整,slew);偏差一旦超过 MaxAllowedPhaseOffset,就会直接设置时钟(阶跃调整,step)。12 而且,当偏差超过 MaxPosPhaseCorrection/MaxNegPhaseCorrection(独立配置默认 54,000 秒 = 15 小时)时,就会不再校正、只记录事件2 遇到「明明在同步却怎么都对不上」的情况,很可能就是撞上了这个上限。而且阶跃调整同样可能朝负方向进行,也就是说Windows 的系统时钟是有可能向后跳的── 这一点会引出后半部分关于应用设计的话题。

3. w32tm 命令实务 ── 查看现状、实测差值、变更同步目标

在时刻相关的排查中,实际用到的命令一共只有 5 个,全部都要在具备管理员权限的命令提示符下执行。2

首先是查看现状。

w32tm /query /status

うるう秒インジケーター: 0(警告なし)
階層: 4 (二次参照 - (S)NTP で同期)
精度: -23 (ティックごとに 119.209ns)
ルート遅延: 0.0312500s
ルート分散: 7.7756348s
参照 ID: 0xC0A80A14 (ソース IP:  192.168.10.20)
最終正常同期時刻: 2026/07/22 8:14:02
ソース: dc01.example.local
ポーリング間隔: 10 (1024s)

需要重点关注的是三点:「ソース」(来源) 是否是预期的对象(如果是 Local CMOS ClockFree-running System Clock,就实质上处于未同步状态),「最終正常同期時刻」(最后一次成功同步时间) 是否是最近的时间(如果是好几天前,说明同步没有在起作用),「階層」(Stratum,层级) 是否合理(距离准确的时刻源有多少段,w32time 只接受 Stratum 15 以下)。7 只想知道同步源时用 w32tm /query /source,查看多个同步目标状态时用 w32tm /query /peers,查看设置值及其来源(策略还是本地)时用 w32tm /query /configuration

以上输出来自日语区域设置(locale)的 Windows。在英语环境下项目名称会不同,这里列出对应关系,供与海外据点人员沟通、或用英语搜索资料时参考。另外要注意,由于显示名称会随区域设置而变化,请不要编写按这份输出机械解析的脚本

日语区域设置下的显示 英语区域设置下的显示
うるう秒インジケーター Leap Indicator
階層 Stratum
精度 Precision
ルート遅延 Root Delay
ルート分散 Root Dispersion
参照 ID ReferenceId
最終正常同期時刻 Last Successful Sync Time
ソース Source
ポーリング間隔 Poll Interval

接下来是实测与对方的时刻差。在故障排查中,这用于把「服务器和这台 PC 现在相差多少」量化成具体数值。

w32tm /stripchart /computer:192.168.10.20 /samples:5 /dataonly

192.168.10.20 [192.168.10.20:123] の追跡中。
現在の時刻は 2026/07/24 9:41:03 です。
09:41:03, +28.1246875s
09:41:05, +28.1250120s
09:41:07, +28.1248533s
09:41:09, +28.1251008s
09:41:11, +28.1249517s

照这个示例即可立刻判断出「这台 PC 比对方慢了约 28 秒」。由于 /stripchart 只是用于显示的测量,不会改变本地时钟,因此可以放心地在正在运行的设备 PC 上使用。在开始比对日志之前,对所有相关机器都执行一遍,先做出偏移量一览表,再着手比对——这是我们在故障排查中最先要做的事。

要明确指定同步目标,需使用 /config。指定公司内部 NTP 服务器(或 DC)的标准做法如下。

w32tm /config /manualpeerlist:"ntp1.example.local,0x8 ntp2.example.local,0x8" /syncfromflags:manual /update
w32tm /resync

0x8 是以客户端模式同步的标志,与 0x1(SpecialInterval)组合(即 ,0x9)后,会按照 SpecialPollInterval 所指定的间隔进行轮询。仅指定 0x1 会导致客户端模式的标志被去掉,因此要指定间隔的话应写成 ,0x8,0x9。如果只能准备两台服务器,建议为其中一台加上 0x2(UseAsFallbackOnly)以明确优先级(Microsoft 的建议是,如果能准备三台以上会更好)。2 要停止手动指定、恢复为域层级同步时,执行 w32tm /config /syncfromflags:domhier /update 并重启服务。w32tm /resync 会丢弃已累积的误差统计并立即重新同步,可用于确认设置变更后的生效情况。2

服务器名后面附加的数值就是 NtpServer 标志。这些内容分散各处容易被用错,这里汇总成一张表。2

标志 名称 含义
0x1 SpecialInterval 轮询间隔由 SpecialPollInterval 注册表值决定
0x2 UseAsFallbackOnly 作为其他时刻源不可用时的备用项
0x8 Client 以客户端模式与该对象同步
0x9 Client + SpecialInterval 0x80x1 的组合。想自行决定间隔时的常用写法

请不要单独指定 0x1由于客户端模式的标志不会被置位,这会变成只指定了间隔却不进行同步的配置。想指定间隔的话,应使用 0x9

缩短工作组 PC 的轮询间隔

第 7 章判断表中提到的「缩短 SpecialPollInterval」,是通过修改注册表值并重启服务来实现的。把默认的 604,800 秒(1 周)改为 3,600 秒(1 小时)的步骤如下。2

rem (1) 将轮询间隔设为 3,600 秒(REG_DWORD 的数值以十进制指定)
reg add "HKLM\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient" /v SpecialPollInterval /t REG_DWORD /d 3600 /f

rem (2) SpecialPollInterval 只对带有包含 0x1 的标志的时刻源生效,需以 0x9 指定
w32tm /config /manualpeerlist:"ntp1.example.local,0x9 ntp2.example.local,0x9" /syncfromflags:manual /update

rem (3) 重启服务使设置生效,并立即同步
net stop w32time && net start w32time
w32tm /resync

rem (4) 确认生效结果,以及各设置值的来源(策略还是本地)
w32tm /query /configuration
w32tm /query /status

如果省略(2),即便只修改注册表,间隔也不会发生变化,因为SpecialPollInterval 只对带有 0x1 标志的时刻源起作用。此外,在通过组策略分发时刻设置的环境中,本地的注册表修改会在下一次策略应用时被覆盖。请通过 w32tm /query /configuration 的输出确认各设置值的来源,如果处于策略管理之下,则应在「计算机配置」>「管理模板」>「系统」>「Windows Time Service」>「Time Providers」>「配置 Windows NTP 客户端」中进行设置。

另外需要注意,通过 /manualpeerlist 指定的外部 NTP 与域内经过认证的时刻是两回事——它不会被认证,因此原则上不应用于域成员机,而是用于顶端(PDC 模拟器)或非域机器。1

4. 关于精度 ── 默认能对到什么程度,1 毫秒的条件

「Windows 的 NTP 同步到底能对到多准」这个问题,答案会因时代而异。

Windows Server 2012 R2/Windows 8.1 及更早版本的 w32time,其设计目标是满足 Kerberos 认证的要求(默认 5 分钟)的精度,并在同一林内提供「大致准确的时刻」,官方明确说明比这更严格的精度要求超出了设计规格、不属于支持范围。4 换句话说,这是一个「只要对到秒级就算符合设计」的世界。

Windows Server 2016/Windows 10 1607 之后改进了算法,默认的时钟更新频率也大幅提高(例如:服务器的时钟调整从每小时一次提升到每秒一次)。3 结果就是,只要满足条件,1 秒、50 毫秒、1 毫秒的精度被定义为支持边界。1 毫秒精度的主要条件如下,反过来说,如果环境不满足这些条件,就不应期待能达到 1 毫秒。4

  • 以准确且稳定的 Stratum 1 时刻源(如 GPS 时钟)为顶端的 NTP 层级结构,且路径上的所有 Windows 机器均为高精度配置
  • 与时刻源之间的网络延迟低于 0.1 毫秒,且距时刻源在 Stratum 5 以内、4 跳以内
  • 各层级的 CPU 使用率(按日平均)不超过 80%(在虚拟化环境中主机也需满足)

此外,像 time.windows.com 这样的互联网远程时刻源,会受到路径不对称与拥塞的影响,因此不能指望达到 1 毫秒精度7 从实务经验来看,按「默认的工作组 = 可能相差秒级至数十秒」「配置得当的公司内部 NTP 同步 = 数十毫秒至 1 秒以内」「使用专用时刻源并专门设计 = 毫秒级」这三档来把握,是比较稳妥的。如果设备联动需要毫秒级的先后关系,就不应依赖时刻同步,而应如后文所述,转向用单侧时钟来测量的设计。

5. 虚拟机的时刻 ── Hyper-V 时刻同步集成服务与 NTP 的双重关系

虚拟机的时刻比物理机更容易出问题,原因很简单:提供时刻的对象有两套。Hyper-V 来宾机上的 Windows,同时拥有从主机获取时刻的 Hyper-V 时刻同步集成服务(VMICTimeSync 提供程序),以及普通的 NTP 客户端,Windows 会依次按层级(Stratum)、根延迟、根离散度、偏移量来挑选「更优的一方」。7

Windows Server 2016 大幅改进了这一机制:VM 启动、恢复时的初始时刻变得准确,经过中断延迟校正的样本也会传递给 w32time,从而能相对于主机保持约 10 微秒的精度。主机向来宾机报告的 Stratum 也变成了符合实际情况的「主机 Stratum + 1」,已加入域的 2016 及以后版本的来宾机,不再单纯依赖主机,而是会自行选择最准确的时钟3

另一方面,在域中运行 Windows Server 2012 R2 及更早版本的来宾机时,Hyper-V 时刻同步提供程序有可能扰乱域的时刻同步,因此 Microsoft 建议禁用该提供程序。3

reg add HKLM\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\VMICTimeProvider /v Enabled /t REG_DWORD /d 0 /f
net stop w32time && net start w32time

关于 Azure VM 也有相应的整理,要点是「已加入域的 VM(尤其是虚拟化的 DC)应禁用 TimeSync、统一到域层级同步;非域的单独 VM 则保持默认的主机同步」。3 第三方虚拟化平台(如 VMware)的思路也相同,对于已加入域的来宾机,建议关闭主机端的时刻同步功能。3 如果出现「NTP 与主机同步交替拉扯时钟,导致日志时刻忽前忽后」的症状,应怀疑是这种双重关系在作祟。另外补充一点运维上的注意事项:从 VM 的保存状态恢复,或刚完成实时迁移之后,时刻会从较大的偏差状态开始校正,因此刚恢复后的日志时刻尤其不可轻信

6. 业务系统一侧的设计 ── 以「时刻会偏移、会倒退」为前提来构建

到这里为止讲的都是基础设施一侧的内容,但无论把时刻同步调整得多么完善,偏差都不会归零。开发设备联动软件的一方,需要以时刻会偏移,也可能倒退为前提,来设计日志记录与时间测量。

第一原则是,日志时间戳以 UTC 记录。若以本地时间记录,时区、夏令时以及各设备之间的设置差异都会妨碍比对(这个话题在《业务应用的日期时间与时区》中有详细讨论)。第二原则是,根据「何时发生」与「花费多久」来区分使用不同的时钟

// 【陷阱】用系统时钟测量经过时间
// 一旦 w32time 进行阶跃校正,这个差值就可能比实际更长、更短,甚至变成负数
var start = DateTime.UtcNow;
ExecuteInspection();
var elapsed = DateTime.UtcNow - start;   // 用于超时判定会误报

// 【定式】经过时间用 Stopwatch(单调递增时钟)测量
long t0 = Stopwatch.GetTimestamp();
ExecuteInspection();
TimeSpan elapsed2 = Stopwatch.GetElapsedTime(t0);   // .NET 7 及以后。更早版本用 Stopwatch.StartNew()

Stopwatch 是专门用于测量经过时间的类,它通过高分辨率性能计数器(相当于 QueryPerformanceCounter)计数刻度,不受系统时钟校正的影响。5 而 DateTime.UtcNow 本身就是系统时钟,分辨率也取决于系统计时器(大致为 0.5~15 毫秒)。6 超时判定、重试间隔、性能测量、设备响应时间测量──凡是处理「时长」的场景,全部交给 Stopwatch 一侧。

日志中两者都要并列记录。让挂钟时间(UTC)与单调时钟成对保存下来,之后即便区间跨越了 NTP 的阶跃校正,也能还原出事件的顺序与间隔。

public sealed class OpLog
{
    private static readonly long _baseTimestamp = Stopwatch.GetTimestamp();
    private static long _seq;

    public static void Write(string message)
    {
        long seq = Interlocked.Increment(ref _seq);
        // UTC 时刻(何时发生)+ 自启动以来的单调经过毫秒数(顺序与间隔)+ 序号(同一时刻内的顺序)
        var line = $"{DateTime.UtcNow:yyyy-MM-dd'T'HH:mm:ss.fff'Z'}\t" +
                   $"{Stopwatch.GetElapsedTime(_baseTimestamp).TotalMilliseconds:F1}\t" +
                   $"{seq}\t{message}";
        // ... 输出到文件/ETW
    }
}

面向多台机器与设备之间的日志比对,再补充两点。其一是,定期记录与对方时钟之间的偏移。像摄像机、PLC 这类拥有自身时钟的设备,往往可以通过通信协议读取设备时刻,因此在应用启动时以及定期(例如每小时一次)将「PC 的 UTC 时刻与设备时刻之差」记入日志。这相当于 w32tm /stripchart 的设备版,故障发生后就能机械化地完成「这段期间,设备日志的时刻要加上 +12.3 秒的校正来读」这类比对。其二是,让事件日志、ETW 一侧的记录与自建日志的时刻体系保持一致(参见《Windows 事件日志・ETW 入门》)。在崩溃时的证据设计(《崩溃时保留日志与转储的设计》),以及像摄像机通信中断这类由网络引发的故障排查(《TCP 重传导致工业相机通信中断》)中,时刻体系是否一致,会让排查时间相差一个数量级。

在离线的工厂局域网(不联网)中,由于无法访问 time.windows.com,在局域网内搭建本地 NTP 服务器、让所有设备都对齐到它是标准做法。如果有 GPS 时钟当然理想,但即便没有,只要能做到「绝对时刻或许有些许偏差,但所有设备都对齐到同一个基准」,日志比对的目的也基本能够达成。对于基准服务器,还可以考虑调整 LocalClockDispersion──它决定了在无法与外部同步期间自我申报的精度。2

7. 按环境划分的判断表

环境 默认同步目标・频率 容易出现的症状 推荐操作
已加入域的 PC/服务器 DC(NT5DS)→顶端为 PDC 模拟器1 整个域一起与外部产生偏差 在 PDC 模拟器上通过 /manualpeerlist 设置外部准确的时刻源,成员机保持默认设置
工作组 PC time.windows.com,默认约每周一次、频率较低2 数十秒的偏差成为常态 通过 /manualpeerlist(,0x9 = Client + SpecialInterval)指定公司内部 NTP,并缩短 SpecialPollInterval(例如 3,600 秒)。具体命令步骤见第 3 章「缩短工作组 PC 的轮询间隔」
Hyper-V/Azure VM(已加入域) 主机(VMIC)与 NTP 两套7 双重校正导致时刻摇摆,恢复后立即出现大幅偏差 若主机与来宾机都是 2016 及以后版本,默认即可共存。2012 R2 及更早版本的来宾机应禁用 VMICTimeProvider3
Hyper-V/Azure VM(单独) 同上 基本没有问题 保持默认设置,使用主机同步3
离线工厂局域网 无同步目标(依赖各机器的内置时钟) 所有设备各自漂移、参差不齐 以本地 NTP 服务器为基准,让所有设备(PC・装置)对齐。定期记录与设备时钟的偏移量
需要毫秒级先后关系 ── 时刻同步的精度不够 确认是否满足 Windows Server 2016 及以后 + 高精度配置的条件4。如果可行,转向用单侧机器的 Stopwatch 测量的设计

8. 总结

  • Windows 的时刻由 w32time 管理:在域中是以 PDC 模拟器为顶端的层级同步,在工作组中默认是与 time.windows.com 的低频同步。数十秒的偏差不是故障,而是默认设置带来的结果。
  • 排查应从用 w32tm /query /status 确认同步源与最后同步时刻、用 w32tm /stripchart 实测与对方的差值开始。明确指定同步目标用 /config /manualpeerlist,立即生效用 /resync
  • w32time 对小幅偏差进行平滑调整,对大幅偏差进行阶跃校正。请务必记住:系统时钟也可能向后跳,且一旦超过上限就不会被校正。
  • 默认设置的精度目标,历来只是满足「Kerberos 的 5 分钟」这一程度。毫秒级精度是 Windows Server 2016 及以后版本、在满足准确时刻源、延迟、跳数、CPU 负载等条件时的支持范围。
  • 虚拟机拥有主机同步与 NTP 两套体系。已加入域的 VM 原则上应统一为域同步(旧版操作系统的来宾机需禁用 VMICTimeProvider),单独 VM 原则上保持主机同步。
  • 应用一侧要区分使用:时间戳用 UTC,经过时间用 Stopwatch,并定期记录与设备自身时钟之间的偏移量。做到这三点,就能摆脱「分不清谁先谁后」的故障排查困境。

相关文章

相关咨询领域

合同会社小村软件承接如下相关业务:针对「设备与 PC 之间日志时刻对不上、无法确定故障先后关系」等问题的排查咨询,工厂局域网・设备联动环境下的时刻同步设计,以及包括超时与时间测量相关缺陷在内的设备联动软件开发与改进。

参考链接

  1. Microsoft Learn, How the Windows Time Service Works。关于 w32time 是使用 NTP 规范中一系列算法的 Windows 标准时刻同步服务、AD DS 林的时刻层级结构(成员 → DC → 父域 DC → 林根域 PDC 模拟器)、非域机器默认与 time.windows.com 同步、通过 Kerberos 会话密钥对时刻进行认证、手动指定的时刻源不会被认证、平滑调整/阶跃调整的时钟规律,以及使用 UDP 123 端口。  2 3 4 5 6 7 8

  2. Microsoft Learn, Windows Time service tools and settings。关于 w32tm 命令的各项选项(/query /status・/source・/peers・/configuration、/stripchart、/resync、/config /manualpeerlist /syncfromflags)、NtpServer 标志(0x1 SpecialInterval・0x2 UseAsFallbackOnly・0x8 Client)以及两台服务器配置时推荐使用 0x2、独立配置的默认值为 time.windows.com,0x1 且 SpecialPollInterval 默认为 604,800 秒、由 MaxAllowedPhaseOffset 决定平滑调整/阶跃调整的切换、超过 MaxPos/MaxNegPhaseCorrection(独立配置默认 54,000 秒)时仅记录事件、以及 LocalClockDispersion。  2 3 4 5 6 7 8 9 10 11 12 13

  3. Microsoft Learn, Time accuracy improvements for Windows Server 2016。关于 Hyper-V TimeSync 服务的改进(VM 启动/恢复时的初始时刻、中断延迟校正、报告「主机 + 1」的 Stratum、已加入域的 2016 来宾机会选择最优时钟)、对 2012 R2 及更早版本已加入域的来宾机建议禁用 Hyper-V 时刻提供程序及 VMICTimeProvider 注册表设置、Azure VM 的方针(已加入域的应禁用 TimeSync、单独 VM 则继续使用主机同步),以及默认轮询/时钟更新频率的版本对比(2012 R2 一代的独立配置为每周一次,2016 为每秒时钟更新)。  2 3 4 5 6 7 8 9 10

  4. Microsoft Learn, Support boundary for high accuracy time。关于 Windows 10 1607/Windows Server 2016 之前的 w32time,其设计目标是满足 Kerberos v5 要求的精度、高精度不在支持范围内;2016 及以后版本在满足条件时支持 1 秒/50 毫秒/1 毫秒精度;以及 1 毫秒精度的条件(Stratum 1 时刻源、网络延迟低于 0.1 毫秒、Stratum 5 以内・4 跳以内、CPU 使用率 80% 以下等)。  2 3 4

  5. Microsoft Learn, Stopwatch Class (System.Diagnostics)。关于 Stopwatch 是用于精确测量经过时间的类,在硬件与操作系统支持的情况下会通过高分辨率性能计数器计数刻度、Frequency/GetTimestamp 可以替代 QueryPerformanceFrequency/QueryPerformanceCounter 使用,以及通过 GetTimestamp 与 GetElapsedTime 进行测量。  2

  6. Microsoft Learn, DateTime.UtcNow Property。关于 DateTime.UtcNow 返回的是计算机当前日期时间(UTC),也就是系统时钟,以及其分辨率取决于系统计时器、大致为 0.5~15 毫秒。  2

  7. Microsoft Learn, Accurate Time for Windows Server 2016。关于 Hyper-V 来宾机会从主机的 VMIC 提供程序与 NTP 等多个提供程序中,以 Stratum 等为基准挑选最佳时刻源、独立机器的默认值为 time.windows.com、远程时刻源无法依赖 1 毫秒精度、w32time 只接受 Stratum 15 以下、以及准确时刻的 3 项要件(稳定的时刻源・稳定的客户端时钟・对称的 NTP 通信)。  2 3 4

共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。

与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。

本文与以下服务页面相关联,欢迎从最接近的入口查看。

常见问题

汇总了咨询这一主题时常见的问题。

PC 的日志和设备的日志时刻对不上,首先应该确认什么?
首先在 PC 一侧执行 w32tm /query /status,确认「ソース」(来源,即正在与什么同步)和「最終正常同期時刻」(最后一次成功同步的时间)。如果来源显示为 Local CMOS Clock,或者最后一次同步是好几天前,那么这台 PC 实质上没有与任何对象同步。接下来用 w32tm /stripchart /computer:对方 /dataonly 实测与对方(服务器或设备的 NTP 端口)之间的时刻差,用具体数值确认是哪一方偏差了多少。如果设备一侧拥有自己的时钟,通过设备的时刻设置界面或通信读取设备时刻,记录下与 PC 时刻的差值,这份记录在比对历史日志时也能派上用场。
工作组环境下的 Windows 大约以多高的频率进行时刻同步?
未加入域的 Windows 默认会与 time.windows.com 同步,但频率设置得相当低。注册表默认的 SpecialPollInterval 在独立配置下为 604,800 秒(1 周),即使是 Windows 10 客户端,同步频率也大约是每天一次。PC 内置时钟每天出现秒级至数十秒级的偏差并不罕见,因此在这种频率下,无法期待能达到经得起业务日志比对的精度。在需要日志时刻精度的现场,标准做法是用 w32tm /config /manualpeerlist 指定公司内部的 NTP 服务器,并缩短 SpecialPollInterval。
Hyper-V 上的虚拟机,时刻应该对齐主机还是 NTP?
Hyper-V 来宾机拥有 Hyper-V 时刻同步集成服务(VMICTimeSync)与 NTP 客户端这两个时刻提供程序,Windows 会以层级(Stratum)等为基准挑选更优的一方。已加入域的来宾机,原则上应与域层级(DC)同步;如果主机/来宾机都是 Windows Server 2016 及以后版本的组合,两者已改进为可以共存。若在域中使用 Windows Server 2012 R2 及更早版本的来宾机,Microsoft 建议禁用 VMICTimeProvider,统一为域同步。如果是工作组中的单独 VM,保持默认设置、使用主机同步既简单又可靠。
域环境中如果时刻出现大幅偏差,会发生什么?
用于 Active Directory 认证的 Kerberos,默认要求客户端与服务器之间的时刻一致误差在 5 分钟以内。一旦超过这个范围,认证就会失败,共享文件夹的访问、组策略应用等域的基本功能都会无法正常工作。已加入域的 PC 默认会与 DC 同步,最终以林根域的 PDC 模拟器为顶端的层级结构同步,因此通常不会出现这么大的偏差。反过来说,如果 PDC 模拟器本身没有与外部准确的时刻源同步,整个域就会变成「一起对齐到错误的时刻」,所以确认顶端的设置非常重要。
为什么不能用 DateTime.UtcNow 测量经过时间?
因为 DateTime.UtcNow 读取的是系统时钟,会直接受到 w32time 校正的影响。当时刻差较大时,w32time 不会进行逐步校正(平滑调整),而是直接设定时钟(阶跃调整),此时时刻既可能向前跳,也可能向后跳。也就是说,用 UtcNow 相减测出的经过时间,可能比实际更长、更短,甚至变成负数,这三种情况都有可能发生。测量经过时间或超时判定时,应使用与系统时钟无关、单调递增的 Stopwatch(或 Stopwatch.GetTimestamp),而把 UtcNow 明确限定为只用于记录「何时发生」,这样才安全。

作者简介

本文作者的个人简介页面。

Go Komura

小村软件有限公司 代表

以 Windows 软件开发、技术咨询与故障排查为中心,擅长难以复现的故障调查,以及既有资产仍在运行的项目。

返回博客列表