前几天线上新上线一个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 一起来实践,验证过程如下: