• 聊聊当业务数据时间和预期的不一样,可以从哪些方向排查


    前言

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

    总结

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

  • 相关阅读:
    231. Power of Two
    204. Count Primes
    205. Isomorphic Strings
    203. Remove Linked List Elements
    179. Largest Number
    922. Sort Array By Parity II
    350. Intersection of Two Arrays II
    242. Valid Anagram
    164. Maximum Gap
    147. Insertion Sort List
  • 原文地址:https://www.cnblogs.com/linyb-geek/p/14836016.html
Copyright © 2020-2023  润新知