PHP microtime()漂移,外部NTP服务

时间:2014-02-14 23:18:00

标签: php web-services time ntp

我正在为我的云托管服务器上的问题寻找解决方案,其中结果从microtime返回(true);在几分钟内彼此之间的通话之间非常准确,但在一两天内会漂移近一秒钟。我正在使用此结果在异步连接的客户端之间进行同步,并且我需要精确到NIST的精度在< ~10ms左右,如果可能的话。

我知道这可能被认为是偏离主题的,但我能想到的当前最佳选择是定期轮询一些外部服务并以毫秒为单位获取当前的NIST时间。不幸的是,我似乎找不到任何人提供这项服务。如果我需要,我将自己设置一个具有可靠时间响应的第二台服务器并对其进行ping操作,但似乎必须有人在那里解决这个简单的需求。有人知道吗?

3 个答案:

答案 0 :(得分:1)

我找到了以下服务:

http://currentmillis.com/api/millis-since-unix-epoch.php

请记住,对于任何寻找类似解决方案的人来说,网络延迟和一般不可预测因素肯定会使返回值偏离真实时间。你必须将这些效果分解为你正在使用的任何效果!


更新

在使用上述服务几天之后,很明显我需要比目前托管的连接更可靠的可靠性。我的解决方案是构建一个基于PHP的客户端,通过与附近NTP服务器的直接套接字连接实现。在典型的通话中,我的往返时间大约为7到15毫秒。

您的结果可能会有所不同,具体取决于您自己的服务器以及您选择的NTP提供商。您可以找到第2层服务器here,以及使用general pool。正如这些其他帖子中所提到的,不要不断轮询这些提供商,而是限制您的通话并根据通话时间进行调整。

这是我的'客户'代码:

function RemoteNTP($Host) {
    $Sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);  // Create socket
    socket_connect($Sock, $Host, 123);  // Connect over port 123 for NTP
    $Str = "\010" . str_repeat("\0", 47);  // Create string for binary transmission
    $Trip -= round(microtime(true)*1000);  // Grab time of call
    socket_send($Sock, $Str, strlen($Str), 0);  // Send transmission
    socket_recv($Sock, $Response, 48, MSG_WAITALL);  // Receive formatted response
    $Trip += round(microtime(true)*1000);  // Adjust call time variable
    socket_close($Sock);  // Close socket
    $Data = unpack('N12', $Response);  // Format as an array we can work from
    $Secs = $Data[11]-2208988800;  // Convert to secs since 1970, from 1900 for NTP
    $Frac = $Data[12]/4294967296;  // Fraction of sec, out of 2^32 (32 bits)
    $Time = ($Secs*1000)+round($Frac*1000);  // Combine for full ms value
    $Time += round($Trip/2);  // Measure and adjust this for better accuracy
    return $Time;  // Returns number of milliseconds passed since 1970-01-01
}

可以这样调用:

$Ntp = GetRemoteNTP('0.pool.ntp.org');

通过根据持续检查调整$ Trip的修饰符,您可以获得更准确的行程时间,以确定每次调用的外出和后退时间的实际值。 (我实际上跟踪了我的详细信息,但希望以模块化的方式发布,并将选择的跟踪机制留给实施者。)您可以通过在服务器附近的NTP提供商处进行修改来提高可靠性,但是利用游泳池,您可能还想通过将#0的0到0添加到主机网址并为每个请求循环来“循环”您对池服务器的调用。

另请注意,这应该被视为最后的解决方案。 NTP框架经过精心设计,是一个强大而全面的系统,可以保持非常准确的系统时间。这是一个低级别的自我纠正机制,比这样的家庭酿造黑客做得好得多。由于我的具体情况,我采用这里使用的方法;在系统时钟中可能有更好的替代方案,通过nptd自动调整。

答案 1 :(得分:0)

如果在服务器上安装NTP,则服务器上的精度可能会达到10毫秒。它取决于服务器与引用之间的网络距离以及该路由上的网络负载。如果你提出某项服务的HTTP请求,你很幸运能在200ms内获得时间。如果您希望客户在10毫秒的参考时间内准确定时,他们将需要安装NTP,然后他们可能实现您的目标。本地GPS参考将是实现这种准确性的唯一可靠方式。

答案 2 :(得分:0)

高精度时钟同步将成为问题,尤其是在虚拟化环境中。这是建议在虚拟环境中不运行Kerberos / Windows域控制器的确切情况,因为它们会出现高时钟漂移。

也就是说,正确答案当然不是以任何形式向NIST发送垃圾邮件,因为它们提供NTP服务作为礼貌,并且肯定会阻止您进行过多查询。

所做的是询问您的ISP是否有可用于积极同步时钟的NTP服务器,理想情况下是服务器层1或服务器2,并将所有计算机指向该服务器。如果没有,请设置您自己的stratum 2服务器[最好是在金属上,而不是虚拟]并使用它。

一旦你有了一个合适的NTP服务器,那么只需要配置ntpd就可以从那个服务器中经常更新你的时钟,而你的服务器最终不会超过你的10ms限制。

但实际上,我无法摆脱要求这些不同时钟如此紧密同步的感觉,这是一种糟糕的设计选择的症状。您是否可以简单地将这些“异步客户端”的调度信息发送为“从现在开始的X微秒”,而不是将来的完整时间戳?