微服務設計指導-feignclient的compression參數導致報文返回為gzip格式帶來的坑

語言: CN / TW / HK

背景

在實際對接項目中,我們的支付網關的feignclient開啟了compression-on,這是標準的正確的。如下配置代碼片段

feign:
   okhttp:
      enabled: true
   httpclient:
      enabled: false
      max-connections: 1000
      max-connections-per-route: 100
   compression:
      request:
         mime-types: text/xml,application/xml,application/json
         min-request-size: 2048
         enabled: true
      response:
         enabled: true

中台內,我們自己的tomcat、springboot jvm、我們的K8S容器層、我們的NG全部帶着優化參數和配置,因此在像中台內或者是標準的微服務或者是標準的HTTP Restful服務,feignclient均能正確解析。

但是,如果是第三方的tomcat,ng無任何配置,且沒在代碼裏標明這是一個標準的以json返回的restful api,而是用的代碼默認的。那麼第三方返回的整個報文會走“自適應”匹配模式,所以才導致了一些報文是json返回一些報文變成了gzip流返回。而對於gzip流的返回格式如果是java代碼(非resttemplate)的寫法是需要:

  1. 先把gzip流接住後還原;
  2. 再把流轉成String;

這種是非常不正規的手法。

  • 如果説都是以gzip返回那麼可以這麼做;
  • 如果説一些以gzip流返回一些不是gzip流返回,這就很亂了對整體代碼;

這種問題通常測試手法是發現不了的

這種問題,postman, jmeter, restclient都測不出來的,是因為postman, jmeter(4.0+), restclient都自帶了“如果是gzip那麼啟用流解壓後再造型成string“的功能了,因此只有在代碼上一調用才調用的出來。

代碼上可以規避的臨時手法

resttemplate也是自帶gzip流的,如何你用resttemplate是可以完全接住這種不正規的api返回的。

缺點是:resttemplate不據有微服役功能的,且改造需要很長時間,那麼這將導致重大delay。

比較好的解決方法

因此對於這種做法我們可以使用以下手段一招解決

即把feignclient端的compression全部改成off,如下配置代碼片段。即把compression.request.enabled和compression.response.enabled都改成false。即可。

feign:
   okhttp:
      enabled: true
   httpclient:
      enabled: false
      max-connections: 1000
      max-connections-per-route: 100
   compression:
      request:
         mime-types: text/xml,application/xml,application/json
         min-request-size: 2048
         enabled: false
      response:
         enabled: false

隱患

但這件事,會帶來一個隱患,那就是:現在我們把這個參數關了,萬一對方來一個超大的爆文一定會打爆微服務的組件,這塊可以作為風險記錄一下,因為按照正規的我們還是需要開啟這個參數的,因此我們還是需要鼓勵對接方能夠正規化restful接口,正規化web服務器和應用服務器內的設置,如果碰到實在沒辦法了,那麼我們就把feignclient端裏這兩個參數都開成false。