1

设想

我们有一个用 Java 编写的应用程序。它曾经在物理机上流畅运行。已做出迁移到虚拟机的决定。现在,该应用程序在日志的时间戳中经常出现不准确的情况。

插图

虚拟化之前

时间戳 | 来电者 | 信息
00:00:01.735 | 富 | 下载东西
00:00:05.123 | 富 | 下载了一些东西
00:00:05.123 | 酒吧 | 分析某事
...
00:00:08.990 | 富 | 结尾

如您所见,时间戳值在物理机上不断增长。

虚拟化之后

时间戳 | 来电者 | 信息
00:00:01.735 | 富 | 下载东西
00:00:05.123 | 酒吧 | 下载了一些东西
00:00:05.123 | 巴兹 | 分析某事
...
00:00:04.485 | 富 | 结尾

现在,日志表明该过程在下载期间结束。

采取的解决方案

我们已将 VM 与 NTP 服务器同步。这个问题消失了几天。现在又回来了。

问题

  • 我们应该更频繁地同步吗?
  • 我们能想象以某种方式覆盖System.currentTimeMillis()吗?
  • 我们是否应该根据检测到的时间漂移​​来更改日志中的时间戳值?
  • 如何解决虚拟机时间跟踪丢失问题?

主机操作系统: RHEL 6.5
来宾操作系统: RHEL 5.4
虚拟化平台: RHEV 3.4

4

3 回答 3

1

您必须在不同的选项之间进行选择

  • 具有更频繁的时间同步的精确时间,但时间戳排序更不一致......
  • 通过减少时间同步,甚至完全禁用它来获得不太精确的时间,但在时间戳排序方面更加一致......

据我所知,不可能有与硬件计算机相同的精度。

于 2015-08-20T09:36:28.573 回答
1

最后,这是 RHEL 5.4 的一个错误。将客户操作系统升级到 RHEL 5.11 可以解决该问题。

于 2015-11-08T04:23:30.037 回答
1

currentTimeMillis()开箱即用是线程安全的,但是由于它基于操作系统的时钟时间,因此如果系统的时钟时间发生更改,它可能会遭受不准确性,并且容易出现时间漂移(不准确性的累积增加)。

nanoTime()开箱即用不是线程安全的,而是使用系统的“原子钟”(如果可能*),不受系统时钟更改的影响,如果您的目标只是打印时间戳或事件独立,则适用从它,并且在循环中用于依赖于它的操作时不太容易发生时间漂移,尽管在很长一段时间内,时间漂移会变得很明显。

  • * - 一些特定的操作系统根本不提供或支持“原子时钟”,在这些特定情况下,Java只能使用普通时钟。如果您怀疑您的系统可能是其中之一,请用谷歌搜索。
  • * - 我在这里所说的“依赖”操作是指方法或操作被触发或具有依赖于自上次调用相同或不同方法以来经过的时间,例如在游戏循环中。
    • 发生这种情况是因为时间戳就是一个时间戳,它没有考虑操作本身执行所需的时间。

这似乎不是您的情况,但是如果您遇到这样的情况,即您正在实施依赖于时间戳的操作,如上节最后一个注释中所述,您想要做的是实施一个增量-time,它使用nanoTime()时间戳来获得测量之间经过时间的准确方位,但也允许使用增量。

例如,Delta-time 是做动画的正确方法。

于 2015-11-07T22:35:07.397 回答