异构环境中的时间同步

异构环境中的时间同步

在混合环境中,机器可以在 Windows(大多数)、Linux(少数)下运行,有时在 Android 下运行……实现接近毫秒精度的时间同步的最佳解决方案是什么?

我们正在开发一种基于微服务的解决方案,其中服务分散在我们的设置中的多台机器上。在许多情况下,整合它们之间的信息(日志、监控等)需要一个共同的时间基准。

在 Windows 下使用 NTP 似​​乎有其局限性。有没有任何开源解决方案可以在该操作系统上运行?我们无法保证我们的设置中始终有一台 Linux 机器。

答案1

[编辑] 我刚刚根据记忆记下了旧答案,因此对其进行了重大重写并附上了参考文献。

简短的回答:不。目前,不可能从 x86/x64 平台上的普通操作系统获得近毫秒的精度。

免责声明 这是一个外行人的回答,因为我是一个普通的系统管理员,对计算机有普通系统管理员的看法。一些内核开发人员和硬件架构师可能拥有专业级别的计时知识。

长答案:

总得有个开始。我会从上往下讲,先从应用程序开始,然后往下讲振荡器。

第一个问题不是在一台计算机上计时,而是设法让整个环境就你所拥有的任何计时达成一致。什么计时?事实证明,当今的计算机有几种计时方法。我们最常看到的是系统时间(显示在屏幕的一角)。让我们先假装它很简单,然后在下面的几段中将事情复杂化。

我们希望系统时间正确,并且希望它在所有计算机上保持一致。我们需要一种从可信来源以如此精细的级别传达它的方法,以满足我们的任何要求。

让我们将要求设为 1ms 的容忍度,也就是说,我们的时间可能在我们的环境中偏离 1ms,或者我们错过一个关键目标。让我们具体一点,看看微软能为我们做些什么。

除 NT 等过时的系统外,Windows 本机基于简化的 ntp(从 XP/2003 开始​​的加入域的计算机)或简化的 sntp(从 Win2k 开始的未加入域的计算机)运行计时 - 感谢@Ryan 对这个细节的挑剔。微软设定了两个目标在进行计时实现时,两者都没有达到我们期望的准确度:

“我们不保证也不支持网络上节点之间 W32Time 服务的准确性。W32Time 服务不是满足时间敏感型应用程序需求的全功能 NTP 解决方案。W32Time 服务主要用于执行以下操作:

  • 使 Kerberos 版本 5 身份验证协议正常工作。
  • 为客户端计算机提供宽松的同步时间。

W32Time 服务无法可靠地将同步时间保持在 1 到 2 秒的范围内。此类容差超出了 W32Time 服务的设计规范。

好的。假设我们在多台计算机上运行您的服务堆栈,并且事件关联的计时容差水平接近 1ms,那么这确实令人失望。如果服务堆栈包含两台计算机,我们实际上根本无法使用 Windows 本机计时。但在这期间,让我们强调一下有关 Windows 本机计时的一两个关键点,并附上一些详尽的文档:

如果您有 AD,请注意,给定域中的时间将从 PDC 仿真器角色同步,无论哪个 DC 拥有它。因此,将正确的时间带入域需要通过运行 PDC 仿真器角色的域控制器。如果在多域林中,则转换为林根域的 PDC 仿真器。从那里,时间主要分散到子域的 PDC 仿真器和以扇出方式分散到每个域成员(有一些注意事项)。这个过程是记录在这里. 更多深入信息这里

好的。我们可以做什么呢?

首先,我们需要或者其他更精确的方法来同步整个环境的时间。假设我们不能运行 Linux ntpd 或适用于 Windows 的 ntpd你可以看看一个名为塔迪斯,但可能还有很多可以尝试。

我们在作为 PDC Emulator 运行的 Win2k3 服务器上运行了 Tardis,该服务器的 CMOS 时钟偏差非常大,由于无法解释的历史原因,我们别无选择,只能通过它来同步整个网络。现在,它已被专用的 Linux ntpd 所取代,后者从外部的原子钟中获取时间,这让我们非常高兴,但 Tardis 当时就拯救了我们。但我不知道它是否可以帮助您实现比 Windows 原生更高的精度。

但从现在开始,我们假设我们已经找到了如何实现完美的替代网络时间同步。通过其固有的巧妙性,它能够实现低于一毫秒的容差水平。我们实施它是为了强制执行我们的 AD 期望时间在网络中传播的方式。

这是否意味着我们可以以接近毫秒的粒度从操作系统和微服务中获得准确的诊断?

让我们看看 x86/x64 架构上的操作系统如何安排处理器时间。

它们使用中断,即富含考古学内涵的多面野兽。然而,操作系统并不是唯一一个想要中断的系统。硬件也想中断,而且它有办法做到!(你好键盘)操作系统也参与其中。

这就是事情变得复杂的地方,我将通过过度简化来解决这个问题。有问题吗?我躲开,掩护,并给你指出一个关于这个主题的绝对优秀的论文。(如果你在 Windows 平台上寻找毫秒,你真的应该读一下它。)Win8.1/Win2012r2 的更新版本是据报道正在进行中但尚未公布发布日期。

好的,中断。每当操作系统中发生某事时,中断就会触发后续操作。该操作是从内核获取的一组指令,可以在全部不同的礼仪。底线是,尽管可以根据硬件架构和内核中断处理或多或少准确地确定中断发生的时间,但通常无法确定后续执行部分发生的确切时间。一组特定的指令可能在中断后很早或很晚执行,可能按可预测的顺序执行,也可能不按可预测的顺序执行,可能是硬件故障或驱动程序编写不当导致延迟难以识别。大多数时候人们根本不知道。后续日志文件中显示的毫秒级时间戳 -它非常精确,但是它对于事件发生的时间准确吗?

让我们简要地讨论一下计时中断。中断具有优先级,最低级别是用户应用程序(例如标准服务)获得处理器时间的地方。其他(更高)级别保留用于硬件和内核工作。如果高于最低级别的中断到达,系统将假装队列中任何较低优先级的中断都不存在(直到更高优先级的中断得到处理)。以这种方式运行的普通应用程序和服务将最后获得处理器时间。相比之下,时钟中断几乎具有最高优先级。时间更新几乎总是在系统中完成。这几乎是对其工作原理的过度简化,但它服务于此答案的目的。

更新时间实际上包含两个任务:

  • 更新系统时间/又名挂钟/又名当有人问我现在几点时我所说的话/又名 ntp 相对于附近的系统来回摆弄的东西。

  • 更新滴答数,例如用于测量代码执行的持续时间。

但无论是挂钟时间还是滴答计数,系统从哪里获得时间?这在很大程度上取决于硬件架构。硬件中的某个地方,一个或多个振荡器正在滴答作响,而滴答声是通过一些可能的路径进入与内核联系的接口,因为它以或多或少的精度和准确度更新其挂钟时间和滴答计数。

多核系统中振荡器的放置有多种设计模型,主要的区别似乎是同步与异步放置。本文介绍了这些模型以及它们对精确计时的各自挑战这里例如。

简而言之,同步计时每个多核都有一个参考时钟,其信号分发到所有核心。异步计时每个核心都有一个振荡器。值得注意的是,最新的英特尔多核处理器 (Haswell) 使用某种形式的同步设计,使用称为“QuickPath Interconnect”的串行总线和“转发时钟”,参考。数据表前向时钟的描述方式使得外行(我)可以快速地粗略地掌握它这里

好的,说完了这些书呆子气的话(这表明计时是一项复杂的实际任务,有着丰富的鲜活历史),让我们更深入地看看中断处理。

操作系统使用两种不同的策略之一来处理中断:滴答或无滴答。您的系统使用其中一种,但这些术语是什么意思呢?

滴答作响的内核以固定间隔发送中断。操作系统无法以比滴答间隔更精细的分辨率测量时间。即便如此,执行一个或多个操作所涉及的实际处理也可能包含大于滴答间隔的延迟。例如,考虑分布式系统(如微服务),其中服务间调用固有的延迟可能会消耗相对较多的时间。然而,每组指令都将与一个或多个中断相关联,操作系统以不比内核滴答时间更精细的分辨率测量这些中断。滴答时间有一个基值,但至少在 Windows 中可以根据单个应用程序的需求减少。这是与不仅有好处,还有成本,并携带相当多的细则用它。

所谓的无滴答内核(其名称非常不具描述性)是一项相对较新的发明。无滴答内核以可变间隔(尽可能长的未来持续时间)设置滴答时间。其原因是操作系统动态允许处理器核心尽可能长时间地进入各种休眠级别,目的很简单,就是节省电量。“各种级别”包括全速处理指令、以较低的速率(即较慢的处理器速度)处理或根本不处理。允许不同的内核以不同的速率运行,无滴答内核试图让处理器尽可能不活动,即使在包括排队指令以中断批处理中触发它们的情况下也是如此。简而言之,多处理器系统中的不同内核可以相对彼此在时间上漂移。这当然会对良好的计时造成严重破坏,并且迄今为止是较新的节能处理器架构和无滴答内核尚未解决的问题,这使得它们能够高效地节省电量。将其与滴答内核(静态滴答间隔)进行比较,滴答内核会不断唤醒所有处理器核心,无论它们是否接收实际工作,并且与无滴答内核相比,计时具有一定程度的不准确性,但相对可靠。

标准Windows 滴答时间(即系统分辨率)为 15.6 毫秒直到 Windows 8/2012,默认行为都是无滴答(但可以恢复为滴答内核)。我认为 Linux 默认滴答时间取决于内核编译,但这个利基远远超出我的经验(和这个),因此您可能希望仔细检查是否依赖它。我相信 Linux 内核从 2.6.21 开始都是无滴答编译的,并且可以使用各种标志进行编译以优化无滴答行为(其中我只记得 no_hz 的几个变体)。

裸机系统就这么多了。在虚拟系统中,情况会变得更糟,因为虚拟机和虚拟机管理程序以不同的方式争用,使得精确计时变得极其困难。以下是VMware 概述这是适用于 RHEL KVM 的一个分布式系统也是如此。云系统是甚至更加困难因为我们甚至还没有接近看到实际的虚拟机管理程序和硬件。

总而言之,从系统中获得准确的时间是一个多层次的问题。现在从高层的角度自下而上地讲,我们必须解决:硬件和内核之间的内部时间同步、中断处理和执行我们希望获得时间的指令的延迟、如果在虚拟环境中由于封装了第二个操作系统层而导致不准确、分布式系统之间的时间同步。

因此,在计算历史的这个阶段,我们无法从 x86/x64 架构中获得毫秒级的精度,至少在使用任何普通的操作系统时无法获得这样的精度。

但我们能接近多少呢?我不知道,不同的系统应该有很大差异。掌握自己特定系统的不准确性是一项艰巨的任务。只需看看英特尔建议如何进行代码基准测试从这个角度来看,普通系统(比如我管理的这些系统)已经严重失控。

我甚至没有想过要实现“所有电源优化、英特尔超线程技术、频率调整和涡轮模式功能均已关闭”在关键系统中,更不用说用 C 语言修改代码包装器并运行长期测试以获得后续答案。我只是试图让它们保持活力并尽可能多地了解它们,而不会过多地干扰它们。谢谢时间戳,我知道我不能完全信任你,但我知道你不会错过太多秒数。当实际的毫秒精度变得重要时,一次测量是不够的,需要更多的测量来验证模式。我们还能做什么?

最后,有趣的是实时操作系统人员如何看待中断延迟。还有一个非常令人兴奋的时间同步替代方案正在进行中,其中相当多有趣的统计数据方法白皮书公开。再加上未来的硬件架构和内核开发,几年后计时精度问题可能不再是问题。希望如此。

答案2

time.windows.com 是 Microsoft 操作系统的原生应用。如果您需要更具体的信息,我建议您使用NIST 互联网时间服务器。如果您担心篡改,他们甚至会运行经过身份验证的 NTP。如果这仍然不够,您可以随时运行自己的。有许多供应商销售 1 层或 2 层 NTP 服务器,您只需将其插入您的网络即可。层是指用于验证时间的不同方法。层 1 将仅使用一种方法(NTP、CDMA、GPS),而层 2 将使用两种方法。

相关内容