一次因時區問題引發的血案——儘量別改全局配置

一次因時區問題引發的血案——儘量別改全局配置

緣起

測試報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了,別輕易修改全局配置。

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