在一个混合的环境中,机器可以在Windows(大部分)下运行,Linux(less数),有时候是Android …时间同步的最佳解决scheme的准确度接近毫秒?
我们正在开发一个基于微服务的解决scheme,在我们的设置中,服务分散在多台机器上。 在许多情况下,合并信息(日志,监控等)需要一个共同的时间基础。
在Windows下使用NTP似乎有其局限性。 任何可以在该操作系统上运行的开源解决scheme? 我们不能保证在我们的设置中总会有一台Linux机器。
[编辑]一个主要的重写与参考,因为我只是从记忆中记下旧的答案。
简短的回答:不。 如今,x86 / x64平台上的普通操作系统无法实现近乎毫秒的精度。
长答案: 大胖 免责声明 这是一个俗客的答案。 我只是一个普通的系统pipe理员,具有普通的系统pipe理员对计算机的看法。 在这个答案中,我所处的领域远远超出了我的专业能力,应该仔细检查。 不过,我会尝试提供我所做的陈述的参考资料,将资料与深入的主题联系起来。 甚至有可能我误解了相关的部分,甚至错过了其他的部分。 这是俗话。 我认为可能会在内核开发人员和硬件架构师中寻求专业水平的知识。
一个人必须从某个地方开始。 我将从头开始,从应用程序向下移动到振荡器。
第一个问题是没有在一台计算机上进行计时,而是设法让环境作为一个整体来就任何时间保持一致达成一致。 什么时间? 事实certificate,在今天的计算机中有几种方法来保持时间。 我们所看到的最多的是系统时间(显示在屏幕的一个angular落)。 我们先假装它是简单的,复杂的几段落。
我们希望系统时间是正确的,我们希望它在所有计算机上都是统一的。 我们需要一种方式,将其从一个值得信赖的来源进行沟通,以便达到我们的要求,无论这些要求如何。
让我们的要求变成1ms的容忍度,也就是说,我们的时间可能会偏离我们环境中的1ms,或者我们错过了一个关键的目标。 让我们来具体看看微软能为我们做些什么。
除NT之外,Windows本地计算机基于简化的ntp(以XP / 2003开始的join域的计算机)或简化的sntp(以Win2k开始的非join域的计算机)为基础运行计时 – 感谢@Ryan挑剔这些细节。 微软在制定计时实施时设定了两个目标 ,这两个目标都不包括我们所期望的准确度:
“我们不保证,也不支持networking节点之间的W32Time服务的准确性,W32Time服务不是一个全function的NTP解决scheme,可以满足时间敏感的应用需求,W32Time服务主要是为了以下:
W32Time服务无法将同步时间可靠地保持在一到两秒的范围内。 这些公差超出了W32Time服务的devise规范。“
好。 假设我们在多台计算机上运行服务堆栈,并且事件关联的计时公差级别接近1毫秒,这相当令人失望。 如果服务堆栈包含两台计算机,则实际上根本不能使用Windows本机计时。 但是,当我们处理它时,让我们强调关于Windows本地计时的一个或两个关键点,并包含一些详尽的文档:
如果你有一个AD观察到给定域中的时间将从PDC模拟器angular色同步,无论哪个DC都有。 将正确的时间带入域需要通过运行PDC模拟器angular色的域控制器。 如果在多域林中,则转换为森林根域的PDC模拟器。 从那里,时间主要分散到子域的PDC模拟器,并以扇出的方式分配给每个域成员(有一些注意事项)。 这个过程logging在这里 。
好。 我们可以做什么?
首先,我们需要一个或其他更精确的方法来同步整个环境的时间。 假设我们不能运行Linux的ntpd或ntpd for Windows,你可以看看一个名为Tardis的共享软件客户端,但是可能还有很多可以尝试的东西。
我们在运行PDC模拟器的Win2k3服务器上运行Tardis,这个服务器有一个非常大的偏移的CMOS时钟,由于无法解释的历史原因,我们别无select,只能从中同步整个networking。 现在已经被一个专门的Linux ntpd带来了从外部的primefaces钟带来的时间,取而代之的是很大的快乐,但是Tardis在那里和那里拯救了我们令人钦佩的东西。 但是我不知道它是否可以帮助您实现比Windows本地更高的精度。
但是从这个angular度来看,我们已经想出了如何实现一个完美的替代networking时间同步。 通过其固有的狡猾,它具有低于1毫秒的容差水平的能力。 我们已经制定了这个计划,以实施我们的AD预期的时间如何通过networking传播。
这是否意味着我们能够以接近一毫秒的粒度从操作系统和微服务中获得准确的诊断?
我们来看看x86 / x64架构上的操作系统如何调度处理器时间。
他们使用中断,这是多方面的考古学内容丰富的野兽 。 但是,操作系统并不是唯一的中断欲望。 硬件也希望中断,它有办法做到这一点! (你好键盘)和操作系统一起玩。
这是它变得复杂的地方,我会通过简单的解释来解决这个问题。 有问题吗? 我蹲下来,盖上一个关于这个问题的绝佳的论文 。 (如果你在Windows平台上打毫秒,你真的应该读它..)Win8.1 / Win2012r2的更新版本正在报道中,但没有发布date已经浮出水面。
好,中断。 当操作系统发生什么事时,中断触发下面的动作。 这个动作是从内核中获取的一堆指令,可以通过很多 不同的方式执行 。 最重要的是,尽pipe中断发生在一个时间,根据硬件架构和内核中断处理,或多或less的精度可以确定中断,但后续执行部分的确切时间通常不能。 一组特定的指令可以在中断之后或迟到之后执行,它可以以可预测的顺序执行,也可以是有问题的硬件的受害者,或者影响延迟的写入不良的驱动程序难以识别。 大多数时候人们根本不知道。 后续日志文件中显示的毫秒级时间戳 – 非常精确,但事件发生的时间是否准确?
暂停计时中断。 中断来自优先级,最低级别是用户应用程序(例如标准服务)获得处理器时间的地方。 其他(更高)级别保留用于硬件和内核工作。 如果高于最低级别的中断到达,则系统将假装在队列中的任何较低优先级的中断不存在(直到更高级别的中断已被closures)。 以这种方式运行的普通应用程序和服务将最终符合处理器时间。 相比之下,时钟中断几乎是最高优先级的。 时间的更新几乎总是在一个系统中完成。 这几乎是犯罪过分简单化的一切工作,但它服务于这个答案的目的。
更新时间实际上包含两个任务:
更新系统时间/ AKA挂钟/ AKA当有人问我什么时候是什么时候我说什么/也就是ntp相对于附近的系统来回摆弄一下。
更新滴答计数,用于测量代码执行中的持续时间。
但是,它是墙壁时间还是滴答计数,系统从哪里获得时间? 这很大程度上取决于硬件架构。 在硬件的某个地方,有一个或几个振荡器正在滴答滴答,而滴答是通过几个可能的path之一进入一个与内核接触的界面,因为它以更高或更低的精度和准确性更新了墙壁时间和滴答计数。
在多核系统中有几种devise振荡器的devise模型,主要的区别似乎是同步和asynchronous放置。 举例来说,这些以及它们各自面对精确计时的挑战。
简而言之,同步计时每个多核有一个参考时钟,它将信号分配给所有内核。 asynchronous计时每个核心有一个振荡器。 值得注意的是,最新的英特尔多核处理器(Haswell)采用某种forms的同步devise,使用称为“QuickPath Interconnect”的串行总线和“Forwarded Clocking”,参考文献。 数据表 。 转发时钟的描述是这样的,一个外行(我)可以在这里得到一个快速肤浅的把握。
那么,所有那些神经过敏的东西(这表明计时是一个复杂的实际任务,有很多关于它的生活史),让我们在中断处理时更encryption切。
操作系统hadle中断使用两种不同的策略之一:滴答或无滴答。 你的系统使用一个或另一个,但这些术语是什么意思?
滴答核心以固定的时间间隔发送中断。 操作系统无法以比滴答间隔更高的分辨率来测量时间。 即使如此,执行一个或多个操作所涉及的实际处理也可能包含大于滴答间隔的延迟。 考虑分布式系统(例如微服务),其中服务间通话固有的延迟可能会花费相当多的时间。 然而,每一组指令都将与一个或多个由OS测量的中断相关联,其分辨率不会比内核计时时间更精细。 滴答时间有一个基本的价值,但至less在Windows可以减less个别应用程序的需求。 这不仅与收益相关,而且与成本相关 ,并且带有相当多的细节 。
所谓的无滴答的内核 (非常具有非描述性的名称)是一个相对较新的发明。 无滴答核心以可变间隔(尽可能长的持续时间)设置滴答时间。 原因是操作系统dynamic地允许处理器内核尽可能长时间地进入各种级别的睡眠,其目的是为了节约电力。 “各种级别”包括全速处理指令,处理速度降低(即处理器速度较慢)或根本不处理。 允许不同的内核以不同的速率工作,并且无内核的内核试图让处理器尽可能不活跃,即使在包括排队指令在内的中断批次的情况下也是如此。 简言之,多处理器系统中的不同内核被允许相对于彼此在时间上漂移。 这当然会带来很好的保存时间,至今仍然是一个尚未解决的问题,更新的省电处理器架构和允许他们进行高效省电的无纸化内核。 将它与一个滴答的内核(静态滴答间隔)相比较,它不断地唤醒所有的处理器核心,而不pipe它们是否接受实际的工作,以及计时带有一定程度的不准确性,但与相对可靠的程度相比,无滴答内核。
标准的Windows标记时间(即系统分辨率)是15.6ms ,直到Windows 8/2012默认行为是无滴答的(但是可以恢复到滴答的内核)。 Linux默认的打勾时间我相信取决于内核编译,但这个利基是远远超出我的经验 ( 这也是),所以你可能希望仔细检查,如果你依赖它。 我相信Linux内核是从2.6.21开始无缝地编译的,并且可以用优化无滴答行为的各种标记进行编译(我只记得no_hz的一些变体)。
裸金属系统非常多。 在虚拟系统中,情况越来越糟糕,因为虚拟机和虚拟机pipe理程序以不同的方式进行竞争使得精确的计时非常困难 以下是VMware的概述 , 这里是RHEL KVM的 一个概述 。 分布式系统也是如此。 云系统更加困难,因为我们甚至无法看到实际的pipe理程序和硬件。
总之,从系统中获得准确的时间是一个多层次的问题。 从高层angular度来看,我们必须解决的问题是:硬件和内核之间的内部时间同步,中断处理以及延迟执行指令的执行时间,如果在虚拟环境中不准确由于第二个OS层的封装,分布式系统之间的时间同步。
因此,在计算的历史上,我们不会从x86 / x64架构中获得毫秒级的准确度,至less不会使用任何普通的操作系统。
但是我们能接近多久? 我不知道,不同的系统应该有很大的不同。 掌握自己特定系统的不准确性是一项艰巨的任务。 我们只需要看看英特尔如何build立代码基准testing,以便看到普通系统,比如我发现自己正在pipe理的系统,在这个angular度上是非常失控的。
我甚至都没有尝试在关键系统中实现“所有功耗优化,英特尔超线程技术,频率调整和turbo模式function都closures” ,更不用说C语言中的代码包装,而是运行长期testing来获得后续答案。 我只是尽量让他们活着,尽可能多地学习他们,而不要打扰他们太多。 谢谢你的时间戳,我知道我不能完全信任你,但是我知道你没有太多时间closures。 当毫秒级的实际精度确实变得很重要时,一个措施是不够的,但需要更多的测量来validation模式。 我们还能做什么?
最后,看一下实时操作系统人们如何看待中断延迟是很有趣的。 在作品中还有一个非常令人兴奋的时间同步select ,那里有相当多的有趣的统计数据 , 方法和白皮书被公开。 添加未来的硬件架构和内核开发,并在几年内,这个时间精度的事情可能不再是这样的问题。 人们可能会希望。
本地time.windows.com被微软操作系统使用。 如果你需要更具体的东西,我会build议使用NIST互联网时间服务器 。 他们甚至运行authentication的NTP,如果你担心篡改。 如果这仍然不够,你可以随时运行自己的。 有许多供应商销售第一层或第二层的NTP服务器,您只需插入您的networking即可。 阶层是指用于validation时间的不同方法。 第1层将只使用一种方法(NTP,CDMA,GPS),而第2层将使用两种方法。