一次因时区问题引发的血案——尽量别改全局配置

一次因时区问题引发的血案——尽量别改全局配置

缘起

测试报bug说传入的生日时间戳是651078000000(对应时间是1990-08-20 00:00:00),但是存在数据库是1990-08-19,事关我写的微服务,便决定查一下。

还没解决问题,先发现了feign的bug

  1. 通过postman使用测试给的数据测试了一下,发现还真是有这个问题,怎么会差一天呢,然后考虑到我们微服务之间是使用feign调用的,序列化和反序列化使用的是fastjson,我用postman直接调用微服务序列化和反序列化是jackson,于是决定使用仿真环境调用,先查一下fastjson在fegin调用的时候,序列化完成的数据对不对,于是在feign.SynchronousMethodHandler的第90行代码
Response response;
        try {
            response = this.client.execute(request, this.options);
        } catch (IOException var15) {
            if (this.logLevel != Level.NONE) {
                this.logger.logIOException(this.metadata.configKey(), this.logLevel, var15, this.elapsedTime(start));
            }

            throw FeignException.errorExecuting(request, var15);
        }

response = this.client.execute(request, this.options);这一行打一个断点,请求的时候查一下request的数据,发现出去时就错了,我了个去,然后单步调试发现序列化器用的是jackson,原来配置了fastjson序列化器没生效,去了解了一下feign这个项目发现feign使用的httpconverter和springMVC的不是同一个,于是配置feign的序列化和反序列化器:

@Configuration
public class MyFeignClientsConfiguration {


    @Bean
    public Encoder feignEncoder(){
        return new SpringEncoder(feignHttpMessageConverter());
    }

    @Bean
    public Decoder feignDecoder(){
        return new SpringDecoder(feignHttpMessageConverter());
    }

    /**
     *feign和Springboot使用的都是jackson,可以都修改为fastjson解析方式
     */
    private ObjectFactory<HttpMessageConverters> feignHttpMessageConverter(){
        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(this.getFastJsonConverter());
        return () -> httpMessageConverters;
    }

    private FastJsonHttpMessageConverter getFastJsonConverter(){
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        List<MediaType> supportedMediaTypes = new ArrayList<>();
        supportedMediaTypes.add(MediaType.APPLICATION_JSON);
        supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
        supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
        supportedMediaTypes.add(MediaType.APPLICATION_PDF);
        supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XML);
        supportedMediaTypes.add(MediaType.IMAGE_GIF);
        supportedMediaTypes.add(MediaType.IMAGE_JPEG);
        supportedMediaTypes.add(MediaType.IMAGE_PNG);
        supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
        supportedMediaTypes.add(MediaType.TEXT_HTML);
        supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
        supportedMediaTypes.add(MediaType.TEXT_PLAIN);
        supportedMediaTypes.add(MediaType.TEXT_XML);
        converter.setSupportedMediaTypes(supportedMediaTypes);
        FastJsonConfig config = new FastJsonConfig();
        config.getSerializeConfig().put(JSON.class,new SwaggerJsonSerializer());
        config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
        converter.setFastJsonConfig(config);
        return converter;
    }
}

期间还遇到一个什么content-type不能包含*的错误,通过手动组建supportedMediaTypes数组解决。

feign序列化和反序列化修正后,format有问题

在feign的调用方和服务提供方都添加上上面的配置后,还是有问题,具体表现在feign的调用request中日期是时间戳,并没有问题,feign的服务提供方能接收到调用方传过来的数据,是时间戳,没问题,但是通过SimpleDateFormate输出后还是有问题,这就不得不怀疑SimpleDateFormate的时区用的啥,SimpleDateFormate的时区默认是GMT,后面发现了有人在SpringBoot启动的时候设置了时区:

TimeZone.getTimeZone("GMT+8") 

问题估计就出在这了,查git,发现是某个同事,于是去问了一下原因,得到的解释是logback在客户机上输出的时间不对,所以设置了时区。我晕,想吐槽:日志时间不对去搞logback啊,全局设置时区影响整个服务啊,再说了,日志时间不对和生产数据不对,哪个比较重要?这用屁股想想都优先生产数据。于是果断删除时区设置。

修正logback输出时间

logback配置文件中pattern有:

%d [%thread] %-5p [%c] [%F:%L] [trace=%X{X-B3-TraceId:-},span=%X{X-B3-SpanId:-},parent=%X{X-B3-ParentSpanId:-}] - %msg%n

去翻了一下logback的文档,http://logback.qos.ch/manual/layouts.html,
在这里插入图片描述
根据第二个框的描述,.SSS是可以配置为时区的,于是改pattern为:

%date{yyyy-MM-dd HH:mm:ss.Asia/Shanghai} [%thread] %-5p [%c] [%F:%L] [trace=%X{X-B3-TraceId:-},span=%X{X-B3-SpanId:-},parent=%X{X-B3-ParentSpanId:-}] - %msg%n

耗时一天加一上午解决,如果不设置全局时区的话,这个问题可能就只停留在logback了,别轻易修改全局配置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章