Java时间不同步

时间:2019-01-15 13:29:17

标签: java spring-boot time

最近,我遇到一个非常奇怪的错误,无法在本地复制。它发生在Spring Boot应用程序内的服务器(CentOS)上。

呼叫new Date()java.util.Date)会产生错误的时间。我并不是说由于时区不同而导致的时差。日期时间关闭X分钟。似乎在当前时间之后逐渐开始缺乏。

获得当前系统时钟时间时,这似乎是正确的,但是Java时间正在逐渐增加时差(不是每分钟增加一分钟,而是更慢)。几乎就像JVM存在于具有不同时间定律的时间泡泡中一样。

从长期运行开始,这个问题今天偶然发生了,没有任何问题。

有人可以建议我该如何调试此问题?我一无所知,无法在本地复制此问题(所有操作均在本地计算机上进行。)

编辑:正如我刚刚发现的那样,服务器正在虚拟化的VM堆栈上运行。不过,我不确定具体的硬件配置。

EDIT2:我认为我发现了有问题的部分。导致此问题的组件正在线程池中运行,因此我怀疑池中的所有线程都处于繁忙状态,并且请求已排队,因此处理我设置当前时间戳的请求会逐渐花费更多时间。

示例:

@Async
public Date sendTimeToOtherServer() {
  Date date = new Date()
  // code that sends the date to different server
}

1 个答案:

答案 0 :(得分:1)

Java通过syscall从操作系统获取时间。反过来,这应该从硬件时钟获取时间。

现在,硬件时钟可能会漂移。当您运行虚拟机时,硬件框架可能会模拟硬件时钟,并且漂移可能会超出您的预期。这可能取决于您的VM上的负载...或您的VM以及其他计算硬件上的虚拟机管理程序上的负载。

但是解决方案可能是使用NTP实用程序将VM的系统时钟与可靠的离线时间服务同步。

  

我增加了线程池的大小,并且它开始正确运行,因此它一定是线程池中的这个瓶颈

您可能在这里过早地得出结论。 FWIW,我从未听说过时钟精度取决于Java线程池的大小。


  

我的意思是,线程池可能要花一些时间才能准备好提供一些线程来处理我正在调用新Date()的任务。

啊。我知道了。好吧,如果您正在工作线程中捕获请求开始时间,并且池中没有足够的线程,那么new Date()所获得的结果很可能是准确时间戳(相对于系统时钟);即时间并非不同步。

但是问题是,在这种情况下增加线程池大小是否是一件好事。延迟的请求开始时间是由于工作人员太少还是请求率太高?

  • 在前一种情况下,增加池大小是正确的做法。

  • 在后一种情况下,它没有太大帮助,并且可能使情况更糟。

吞吐量的最终限制因素将是诸如内核数,内存大小,数据库性能,网络带宽等因素。增加线程池 可能允许并行处理更多请求。但是,如果您已经资源匮乏,则不会增加请求的处理速度。确实,过多的工作线程可能导致:

  • 增加了内存使用量和GC负载,并且
  • 单个请求花费的时间太长,以至于客户端使请求超时。