共计 2805 个字符,预计需要花费 8 分钟才能阅读完成。
前言
前些天业务部门的开发共事遇到了一个奇怪的 bug,首先他们有个业务曾经入库的创立工夫和服务器工夫相差了 8 个小时,其次当这个工夫显示到前端后,这个工夫居然和服务工夫相差了好几个月。
明天就这个问题,来做个复盘,来聊聊当业务数据工夫和预期的不一样,能够从哪些方向排查
排查方向
1、数据库和服务器的工夫不统一
1、查看 jdbc 链接配置的时区,即 serverTimezone 的参数配置
注: 本文的时区都以东八区为基准,且数据库为 mysql
示例:
jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
如上图配置的时区是 UTC,这样就和东八区相差 8 个小时。如果按这种配法,当咱们在代码层采纳 new Date()的形式,则落到数据库的工夫会比咱们预期的工夫相差 8 个小时。此时咱们能够把 jdbc 上配置的时区参数改成
serverTimezone=Asia/Shanghai
2、查看数据库默认的时区配置
show variables like '%time_zone%';
由图能够看出,此时数据库时区默认配置不是东八区。咱们能够通过如下办法进行批改
- a、通过命令
## 批改 mysql 全局时区为东八区 | |
set global time_zone = '+8:00'; | |
## 批改以后会话时区 | |
set time_zone = '+8:00'; |
注: 通过命令行,无需重启 mysql 服务,但当 mysql 服务再次被重启,则下面的配置就会隐没
- b、通过配置文件
linux 零碎则编辑 my.cnf,填入如下内容
[mysqld] | |
// 设置默认时区 | |
default-time_zone='+8:00' |
window 的零碎则编辑 my.ini,填入的内容和 linux 一样
注: 批改完配置后,须要重启 mysql 服务
业务部门的创立工夫相差 8 个小时,就是因为他们业务的创立工夫对立是通过数据库配置默认工夫,过后他们数据库默认时区是 UTC,因而相差了 8 个小时。起初通过调整数据库时区解决这个问题
2、容器和服务器的工夫不统一
1、进入容器外部查看工夫
docker exec -it【容器 ID 或者 NAME】bin/bash -c date
2、如果是容器是曾经生成
能够间接把宿主机的 localtime 拷贝到 docker 容器中,前提是宿主机的工夫也是对的。命令如下
docker cp /etc/localtime【容器 ID 或者 NAME】:/etc/localtime
或者间接批改 docker 容器的工夫也能够。进入容器内容,执行 date -s
3、容器生成前,间接通过 dockerfile 配置【举荐】
FROM adoptopenjdk/openjdk8 | |
VOLUME /tmp | |
#ENV JAVA_OPTS="-Dcom.sun.management.jmxremote.port=39083 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false" | |
ENV JAVA_OPTS="" | |
COPY localtime /etc/localtime | |
RUN echo "Asia/Shanghai" > /etc/timezone | |
COPY demo-biz/target/demo-service-biz-*.jar app.jar | |
ENTRYPOINT ["sh", "-c", "exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar"] |
注: 因业务的 dockerfile 是对立依据模板生成,因而就没这个问题
3、工夫格局配置不正确
业务部门为了对立解决工夫格局,在代码中做了如下配置
@Configuration | |
public class WebConfig implements WebMvcConfigurer { | |
@Override | |
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); | |
// 格式化 json 数据格式 | |
FastJsonConfig fastJsonConfig = new FastJsonConfig(); | |
// 序列化时防止精度失落,转换为字符串 | |
SerializeConfig serializeConfig = SerializeConfig.globalInstance; | |
serializeConfig.put(BigInteger.class, ToStringSerializer.instance); | |
serializeConfig.put(Long.class, ToStringSerializer.instance); | |
serializeConfig.put(Long.TYPE, ToStringSerializer.instance); | |
fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue); | |
fastJsonConfig.setSerializeConfig(serializeConfig); | |
fastJsonConfig.setDateFormat("yyyy-HH-dd HH:mm:ss"); | |
fastConverter.setFastJsonConfig(fastJsonConfig); | |
List<MediaType> fastMediaTypes = new ArrayList<>(); | |
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); | |
fastMediaTypes.add(MediaType.APPLICATION_JSON); | |
fastConverter.setSupportedMediaTypes(fastMediaTypes); | |
converters.add(0,fastConverter); | |
} | |
} |
眼尖的敌人,可能发现了那个工夫格局,长得和失常的格局是不一样的。谁能想到,那个奇葩的 bug,居然是因为不小心把工夫格局写错了。解决的办法就很简略了,
fastJsonConfig.setDateFormat("yyyy-HH-dd HH:mm:ss");
改成
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
总结
下面就介绍几种排查方向,尤其是最初一种,因为工夫格局写错,导致工夫显示谬误