前几天线上新上线一个Kafka Java Consumer程序,出现一个异常的问题,那就通过查看日志,数据写入到了Elasticsearch索引里面,但是前端查询不到数据。
最终通过和开发一起定位,是因为我们业务上的原因,默认数据时间戳问题,默认需要使用 UTC TimeZone
;但当运维用 date
命令看的时候,默认是UTC时区啊,为啥还是写错了呢?
因为我们线上维护的是 /etc/localtime
文件来保证时区问题,而且也是 UTC
时区,但是还是写入数据时间对不上,之后上线操作的同事说把 /etc/timezone
文件删除,然后重启消费者程序好了。
好了,这是为啥,虽然知道删除 /etc/timezone
文件后,业务数据写入正常了,但是这是为什么呢,下面我们就来一探究竟。
通常我遇到这种之前没有遇到的问题,都会借助Google搜索一把,搜索完成后,得到JVM加载时区文件顺序如下:
/etc/sysconfig/clock
中文参考链接: https://blog.csdn.net/zj380475045/article/details/72765936 http://www.360doc.com/content/12/1011/17/110467_240881174.shtml
英文参考链接: https://bugs.java.com/view_bug.do?bug_id=6456628
那按照搜索到的结果,跟我的情况不对啊,我们线上删除 /etc/timezone
文件就好了,所以肯定跟文件 /etc/timezone
有关啊,所以我感觉肯定跟操作系统和JAVA版本有关,SO我觉得实践一把,一定要把谜底揭开。
环境 | 操作系统 | JAVA版本 |
---|---|---|
aliyun | Centos6.5 | 1.8.0_25 |
如上表格是我线上环境情况,实践过程如下。
Java测试代码如下:
[root@Labhost2 src]# cat TimeTest.java import java.util.Date; import java.util.TimeZone; public class TimeTest { public static void main(String args[]) { long time = System.currentTimeMillis(); String millis = Long.toString(time); Date date = new Date(time); System.out.println("Current time in milliseconds = " + millis + " => " + date.toString()); System.out.println("Current time zone: " + TimeZone.getDefault().getID()); } } [root@Labhost2 src]# javac TimeTest.java # 生成测试类 [root@Labhost2 src]# ls TimeTest.class TimeTest.java
从搜索我们知道JVM读取时区跟系统变量 TZ
和文件 /etc/sysconfig/clock
、 /etc/localtime
有关,我这里在加上我们删除的文件 /etc/timezone
一起来实践,验证过程如下: