Java时间不同步

Sma*_*ajl 5 java time spring-boot

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

calling 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
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*n C 2

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

现在硬件时钟可能会漂移。当您运行虚拟机时,硬件时钟可能会由虚拟框架模拟,并且可能会比您预期的漂移更多。这可能取决于您的虚拟机上的负载……或者来自您的虚拟机和计算硬件上的其他虚拟机管理程序的负载。

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

我增加了线程池大小,它开始正常运行,所以它一定是线程池中的瓶颈

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


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

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

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

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

  • 在后一种情况下,它不会有太大帮助,而且可能会使事情变得更糟。

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

  • 增加内存使用量和 GC 负载,以及
  • 个别请求花费的时间太长,导致客户端超时。