异构环境中的时间同步

Dav*_*ant 6 linux windows ntp time-synchronization

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

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

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

Eri*_*ikE 14

[编辑] 对参考文献进行了重大重写,因为我刚刚从记忆中记下了旧答案。

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

免责声明 这是一个外行的答案,因为我是一个普通的系统管理员,对计算机有一个普通的系统管理员视图。一些内核开发人员和硬件架构师可能具备专业水平的计时知识。

长答案:

一个人必须从某个地方开始。我将自上而下地执行此操作,从向下移动到振荡器的应用程序开始。

第一个问题不是在一台计算机上计时,而是设法让整个环境就您拥有的计时达成一致。什么计时?事实证明,今天有几种方法可以在计算机中保持时间。我们看到最多的是系统时间(显示在屏幕角落之一)。让我们先假装它是那么简单,然后再把事情复杂化几段。

我们希望系统时间是正确的,我们希望它在我们所有的计算机上都是统一的。我们需要一种方法来从可信来源以如此精细的级别进行通信,以满足我们的要求,无论它们可能是什么。

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

排除过时的 NT 等,Windows 本机基于简化的 ntp(从 XP/2003 开始​​的加入域的计算机)或简化的 sntp(从 Win2k 开始的未加入域的计算机)运行其计时——感谢 @Ryan 对这个细节的挑剔. Microsoft在进行计时实现时设定了两个目标,但都没有包括我们期望的准确度:

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

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

W32Time 服务无法将同步时间可靠地保持在一到两秒的范围内。这种容差超出了 W32Time 服务的设计规范。”

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

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

好的。我们可以做什么?

首先,我们需要一种其他更精确的方法来同步整个环境中的时间。假设我们不能为 Windows运行 Linux ntpd 或ntpd,您可以查看一个名为Tardis的共享软件客户端,但可能还有更多的尝试。

我们在作为 PDC 模拟器运行的 Win2k3 服务器上运行 Tardis,该服务器有一个非常大的 CMOS 时钟,由于无法解释的历史原因,我们别无选择,只能从中同步整个网络。现在它已经被一个专门的 Linux ntpd 取代,它从外部的原子钟中获取时间,但 Tardis 在那一刻和那里拯救了我们。但是,我不知道它是否可以帮助您实现比 Windows 本机更高的精度。

但是让我们假设从这一点开始,我们(我们)已经想出了如何实现完美的替代网络时间同步。通过其固有的狡猾,它具有低于一毫秒的容差水平的能力。我们已将其部署到位,以强制执行我们的 AD 期望时间如何通过网络传播。

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

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

他们使用打断,这是多面的野兽,富含考古物质。然而,操作系统并不是唯一希望中断的。硬件也想中断,它有办法做到!(你好键盘)和操作系统一起玩。

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

好的,打扰了。每当操作系统中发生某些事情时,中断就会触发随后的操作。该行动是一群从内核取出的命令,它可以在执行一大堆不同方式. 最重要的是,尽管中断发生的时间可以根据硬件架构和内核中断处理或多或少地准确确定,但通常无法确定后续执行部分发生的确切时间。一组特定的指令可能在中断后较早或较晚执行,它可能以可预测的顺序执行,也可能不执行,它可能是有缺陷的硬件或写得不好的驱动程序的受害者,甚至难以识别延迟。大多数时候人们根本不知道。显示在后续日志文件中的毫秒级时间戳 -它非常精确,但它是否准确到事件发生的时间?

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

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

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

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

但无论是挂墙时间还是滴答计数,系统从哪里获取时间?这在很大程度上取决于硬件架构。某处的硬件的一个或几个振荡器滴答,而滴答经由带来一个几个可能的路径成一个接口,用于与内核,因为它具有更大或更小的精度和准确度接触更新其壁和时间刻度计数。

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

简而言之,同步计时的每个多核都有一个参考时钟,它将信号分配到所有内核。异步计时每个内核有一个振荡器。值得注意的是,最新的 Intel 多核处理器 (Haswell) 使用某种形式的同步设计,使用称为“QuickPath Interconnect”和“Forwarded Clocking”的串行总线,参考文献。数据表。转发时钟的描述是这样的,外行(我)可以在此处快速了解它。

好吧,抛开所有的书呆子主义(这表明计时是一项复杂的实际任务,有很多关于它的活生生的历史),让我们更仔细地看看中断处理。

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

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

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

在Windows 8/2012 之前,标准的Windows 滴答时间 - 即系统分辨率 - 为15.6 毫秒,其中默认行为是无滴答(但可以恢复为滴答内核)。Linux的默认时钟周期的时间,我相信依赖于内核编译,但这个利基好我的经验之外(而这一次也是如此),所以如果你依赖于它,你不妨仔细检查。我相信 Linux 内核是从 2.6.21 开始编译的,并且可以使用各种优化无滴答行为的标志进行编译(我只记得 no_hz 的几个变体)。

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

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

因此,在计算历史的这一点上,我们不会从 x86/x64 架构中获得毫秒级的精度,至少不会使用任何普通的操作系统。

但我们能走多远?我不知道,它应该在不同系统之间有很大差异。掌握自己特定系统中的不准确性是一项艰巨的任务。只需看看英特尔如何建议进行代码基准测试,就会发现普通系统(例如我碰巧发现自己管理的系统)在这个角度上非常失控。

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

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

  • 很好的答案。只是一个挑剔。现代 Windows 并不真正使用 SNTP。也许 Win 2000/2003/XP 可以,但现在不行了。Windows 时间就像 90% NTP。这是呃...几乎是NTP。不知道为什么微软选择只部分实现NTP。但它是一个自定义实现,它不是 SNTP,但也不完全是 NTP。 (2认同)