zoukankan      html  css  js  c++  java
  • 聊聊当业务数据时间和预期的不一样,可以从哪些方向排查

    前言

    前些天业务部门的开发同事遇到了一个奇怪的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");
    

    总结

    上面就介绍几种排查方向,尤其是最后一种,因为时间格式写错,导致时间显示错误

  • 相关阅读:
    静态代码块执行时机
    java中的命令
    JDBC
    final, finally, finalize
    面向对象
    线程中常用的一些方法
    线程中的yield()
    线程中的join()
    Thread对象 既传入了Runnable对象又重写了run()方法
    Python 绘制词云
  • 原文地址:https://www.cnblogs.com/linyb-geek/p/14836016.html
Copyright © 2011-2022 走看看