在线网页时钟精确到毫秒_Docker Mac版的容器内时钟与系统时钟不一致造成的随机测试失败...

39246ccd07c621acf1e552d57f6c93fb.png

最近我们有一些涉及到数据库的单元测试,本身很简单:

final ZonedDateTime beforeUpdate = ZonedDateTime.now().truncatedTo(ChronoUnit.SECONDS);

repository.upsert(entity);

ZonedDateTime updatedAt = repository.findById(entity.getId()).getUpdatedAt();

ZonedDateTime afterUpdate = ZonedDateTime.now().truncatedTo(ChronoUnit.SECONDS);

assertFalse(updatedAt.isBefore(beforeUpdate));
assertFalse(afterUpdate.isBefore(updatedAt));

updatedAt是数据库的updated_at字段,beforeUpdate/afterUpdate是跑upsert前/后的系统时钟。因为数据库的DATETIME只精确到秒,所以beforeUpdate/afterUpdate也截断到秒。整个测试就是确保updatedAt是发生在beforeUpdate和afterUpdate之间。

这个测试运行时需要连接跑在本地Docker里的一个临时MariaDB server。在Linux上跑一直没问题,在Mac上跑就会有非常小的概率会随机在最后一行fail,也就是说数据库的时钟比系统时钟更快一点。

因为Mac版Docker其实是跑了一个Linux VM,再在VM里跑container,所以怀疑是VM的系统时钟和Mac本机不一致。查了一下果然是:

Addressing Time Drift in Docker Desktop for Mac - Docker Blog​www.docker.com
17a5e6f89367feb8a6c228ab5de01fba.png

原因是不论Host还是VM,读硬件实时时钟(RTC)都是很慢的操作,所以VM内一般用RDTSC来读CPU的time stamp counter(TSC),作为时钟来源。但因为种种原因,这个counter并不可靠,如果不加校正的话,就会出现下面这种情况——每25分钟累积大约1秒的差异。

4c8dd8fefe0f5c5faf20f48505114e4a.png

Docker Mac版想了各种办法来定时纠正这个差异,最后采取的办法是每30秒纠正一次差异,从落后host 15毫秒变成比host快5毫秒:

c329238eb18cefd419c2d2f744202d76.png

而这20毫秒的差异,已经足够使我们的测试在小概率下失败了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值