我们正在开发基于微服务的解决方案,其中服务分散在我们设置中的多台机器上.在许多情况下,在它们之间整合信息(日志,监控等)需要共同的时间基础.
在Windows下使用NTP似乎有其局限性.任何可以在该操作系统上运行的开源解决方案?我们无法保证在我们的设置中总会有Linux机器.
解决方法
简答:不.如今,x86 / x64平台上的普通操作系统无法获得接近毫秒的精度.
答案很长:大胖免责声明@H_301_13@这是一个非专业人士的答案.我只是一个普通的系统管理员,拥有普通的系统管理员计算机视图.在这个答案中,我处于一个远远超出我的专业能力的领域,任何外卖都应该仔细检查.但是,我将尝试提供我所做的陈述的参考,将来源与深入的主题联系起来.有可能甚至可能误解了相关部分而完全错过了其他部分.这就是做好准备.我认为可能在内核开发人员和硬件架构师之间寻求专业知识水平.
一个人必须从某个地方开始.我将自上而下,从应用程序向下移向振荡器开始.
第一个问题是没有在一台计算机上进行计时,而是设法让整个环境达成一致,无论你有什么计时.什么计时?事实证明,有几种方法可以让时间停留在今天的计算机上.我们最常看到的是系统时间(显示在其中一个屏幕角落).让我们首先假装它是简单的,并使几个段落复杂化.
我们希望系统时间正确,我们希望它在所有计算机上保持一致.我们需要一种方法来从一个如此精细的级别的可靠来源进行通信,以便满足我们的要求.
让我们的要求达到1ms的容差水平,也就是说,我们的时间可能在我们的环境中偏离1ms,或者我们错过了一个关键的目标.让我们具体一点,看看微软可以为我们做些什么.
除了NT之类的过时,Windows native基于简化的ntp(以XP / 2003开头的加入域的计算机)或简化的sntp(以Win2k开头的非加入域的计算机)运行其计时 – 感谢@Ryan挑剔这个细节. Microsoft set two goals在进行计时实施时,两者都不包括我们所需的准确度:
“我们不保证,我们不支持网络上节点之间W32Time服务的准确性.W32Time服务不是满足时间敏感的应用程序需求的全功能NTP解决方案.W32Time服务主要用于执行以下:
>使Kerberos版本5身份验证协议正常工作.@H_301_13@>为客户端计算机提供松散的同步时间.
W32Time服务无法将同步时间可靠地保持在一到两秒的范围内.这些容差超出了W32Time服务的设计规范.“
好.假设我们在多台计算机上运行您的服务堆栈,并且事件关联的计时容差级别接近1ms,这是令人失望的.如果服务堆栈包含两台计算机,我们实际上根本无法使用Windows本机计时.但是在我们讨论它的时候,让我们强调一下关于Windows本地计时的关键点,并包括一些全面的文档:
如果您有AD观察到给定域中的时间将从PDC模拟器角色同步,无论哪个DC具有它.因此,需要通过运行PDC模拟器角色的域控制器将正确的时间引入域.如果在多域林中,则转换为林根域的PDC模拟器.从那时起主要分散到子域的PDC模拟器和每个域成员以扇出方式(有一些警告).这个过程是documented here.
好.我们能做什么?
首先,我们需要one或other更精确的方式来同步整个环境的时间.假设我们无法运行Linux ntpd或ntpd for Windows,您可以查看名为Tardis的共享软件客户端,但可能会有更多的尝试.
我们在运行为PDC仿真器的Win2k3服务器上运行Tardis,它具有一个非常大的偏差的CMOS时钟,由于无法解释的历史原因,我们别无选择,只能从中同步整个网络.现在它被一个专用的Linux ntpd取代了巨大的喜悦,从外面的原子钟带来了时间,但是Tardis在当时和那里拯救了我们令人钦佩.但我不知道它是否可以帮助您实现比Windows原生更高的精度.
但是我们从这一点开始假设我们(我们)已经找到了如何实现完美的替代网络时间同步.通过其固有的狡猾性,它具有低于1毫秒的容差水平的能力.我们已将其付诸实施,以强制我们的AD希望时间通过网络传播.
这是否意味着我们可以在接近单毫秒的粒度下从操作系统和微服务中获得准确的诊断?
让我们看一下x86 / x64架构上的操作系统如何安排处理器时间.
它们使用中断,即multifacetted beasts rich in archaeological substance.然而,操作系统并不是唯一一个打算中断的中断.硬件也希望中断,它有办法做到这一点! (Hello键盘)和操作系统一起玩.
这是它变得复杂的地方,我将通过过度简化来解决这个问题.有问题吗?我躲开,覆盖并指向你absolutely excellent treatise on the subject.(如果你在Windows平台上搜索毫秒,你真的应该读它..)Win8.1 / Win2012r2的更新版本是reportedly in the works但是没有发布日期.
好的,中断.每当OS中发生某些事情时,中断就会触发随后的操作.该操作是从内核获取的一堆指令,可以在different manners的whole lot中执行.最重要的是尽管中断发生的时间可以根据硬件架构和内核中断以或多或少的精度确定处理,后续执行部分发生的确切时间通常不能.一组特定的指令可以在中断之后或之后的早期执行,它可以以可预测的顺序执行或不执行,它可能是有缺陷的硬件或写得不好的驱动程序的受害者,这些驱动程序影响难以识别的延迟.大多数时候,人们根本不知道.毫秒级别的时间戳,显示在后续日志文件中 – it is very precise,but is it accurate as to when the event happened?
让计时中断暂时停止.中断带有优先级,最低级别是用户应用程序(例如标准服务)获得处理器时间的位置.其他(更高)级别保留用于硬件和内核工作.如果高于最低级别的中断到达,系统将假装队列中的任何较低优先级中断都不存在(直到更高的prio中断被关注).以这种方式运行的普通应用程序和服务将是处理器时间的最后一行.相比之下,时钟中断几乎具有最高优先级.时间的更新几乎总是在系统中完成.这几乎是一种过于简单的过分简化,但它服务于这个答案的目的.
更新时间实际上包含两个任务:
>更新系统时间/ AKA挂钟/ AKA当有人问我现在是什么时候我说什么/ AKA东西ntp相对于附近的系统来回摆动一下.@H_301_13@>更新刻度计数,例如在代码执行中测量持续时间时使用.
但是它是壁挂时间还是滴答计数,系统从哪里获得时间?它在很大程度上取决于硬件架构.在硬件中的某个地方,一个或多个振荡器正在滴答作响,并且通过several paths paths将该滴答带入与内核接触的接口,因为它具有更高或更低的精度和准确度,更新其壁时间和滴答计数.
在多核系统中有多种用于振荡器放置的设计模型,主要区别似乎是同步放置和异步放置.例如,在here中描述了这些以及它们对精确计时的各自挑战.
简而言之,同步计时每个多核有一个参考时钟,它将信号分配给所有核心.异步计时每个核心有一个振荡器.值得注意的是,最新的英特尔多核处理器(Haswell)使用称为“QuickPath Interconnect”和“转发时钟”的串行总线进行某种形式的同步设计.转发时钟的描述是这样的,外行人(我)可以快速地对它进行快速掌握here.
好吧,所有那些神经质的东西(这表明计时是一项复杂的实际任务,有很多关于它的生活历史),让我们看看中断处理更接近.
操作系统使用两种不同策略中的一种来中断:滴答或无滴答.您的系统使用其中一种,但这些术语的含义是什么?
Ticking内核以固定间隔发送中断.操作系统无法以比滴答间隔更精细的分辨率测量时间.即使这样,执行一个或多个动作所涉及的实际处理也可能包含大于刻度间隔的延迟.例如考虑分布式系统(例如微服务),其中服务间调用中固有的延迟可能消耗相当多的时间.然而,每组指令将与OS测量的一个或多个中断相关联,其分辨率不比内核滴答时间更精细.滴答时间具有基值,但至少在Windows中可以根据需要由单个应用程序减少.这是一个与not only with benefits but also with costs相关的动作,随身携带quite a bit of fine print.
所谓的tickless kernels(具有非描述性名称)是一项相对较新的发明.无滴答内核以可变间隔设置滴答时间(尽可能长的持续时间).原因是操作系统动态地允许处理器内核尽可能长时间地进入各种睡眠级别,其目的是节省功率. “各种级别”包括全速处理指令,以递减速率处理(即较慢的处理器速度)或根本不处理.允许不同的核以不同的速率运行,并且无滴答的内核试图让处理器尽可能地处于非活动状态,即使在包括排队指令以在中断批处理中将它们关闭的情况下也是如此.简而言之,允许多处理器系统中的不同核心相对于彼此漂移.这当然会对保持良好的时间造成严重破坏,并且迄今为止尚未解决的问题是更新的省电处理器架构和无滴答内核,它们可以实现高效节能.将其与滴答内核(静态滴答间隔)进行比较,该内核不断地唤醒所有处理器内核,无论它们是否接收实际工作,并且计时带来一定程度的不准确性,但与无滴答内核相比具有相对可靠的程度.
标准Windows tick time – that is the system resolution – is 15.6ms直到Windows 8/2012,默认行为是无定形的(但可以恢复为内核). Linux默认的滴答时间我相信取决于内核编译,但this niche是well outside my experience(也是this one)所以你可能希望仔细检查你是否依赖它.我认为Linux内核是从2.6.21开始编译的,可以使用各种标志进行编译,优化无滴答行为(其中我只记得no_hz的一些变体).
对于裸机系统来说非常重要.在虚拟系统中,它变得更糟,因为VM和虚拟机管理程序以不同方式进行争用会使准确的计时变得非常困难.这是an overview for VMware和here is one for RHEL KVM.分布式系统也是如此.云系统是even more difficult,因为我们甚至没有看到实际的虚拟机管理程序和硬件.
总之,从系统中获取准确的时间是一个多层次的问题.从高层来看现在自下而上,我们必须解决:硬件和内核之间的内部时间同步,中断处理和延迟执行我们希望时间的指令,如果在虚拟环境中不准确由于第二OS层的封装,分布式系统之间的时间同步.
因此,在计算历史的这一点上,我们不会从x86 / x64架构中获得毫秒级精度,至少不使用任何普通的操作系统.
但我们能接近多远?我不知道,不同的系统之间应该有很大差异.掌握自己特定系统中的不准确性是一项艰巨的任务.人们只需要看how Intel suggests code benchmarking should be done就可以看到普通的系统,比如我碰巧发现自己管理的系统,从这个角度来看,它们已经非常失控.
我甚至没有考虑在关键系统中实现“所有功率优化,英特尔超线程技术,频率调整和turbo模式功能”,更不用说修补C中的代码包装并运行长期测试以获得后续答案.我只是试着让他们活着,尽可能多地学习他们,而不会过多地打扰他们.谢谢你的时间戳,我知道我不能完全信任你,但我知道你不是太多的秒.当实际的毫秒精度变得很重要时,一项措施是不够的,但需要更多的测量来验证模式.我们还能做什么?
最后,有趣的是看how the realtime OS-people think interrupt latency.还有一个very exciting time synch alternative正在开发中,相当有趣的statistics,methodology和whitepapers被公之于众.添加未来的硬件架构和内核开发,在几年内,这种计时准确性可能不再是这样的问题.人们可能希望.