spring cloud feign gzip 压缩问题

{"msg":"JSON parse error: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\\r, \\n, \\t) is allowed between tokens; nested exception is com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\\r, \\n, \\t) is allowed between tokens\n at [Source: (PushbackInputStream); line: 1, column: 2]","code":500}

最近开发spring cloud的一个项目,项目中需要用到跨模块之间的调用,在开发的过程中,前期开发测试没有任何问题,代码开发完成时,在联调时出现了问题

具体描述如下:当参数过多时,会报{"msg":"JSON parse error: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\\r, \\n, \\t) is allowed between tokens; nested exception is com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\\r, \\n, \\t) is allowed between tokens\n at [Source: (PushbackInputStream); line: 1, column: 2]","code":500}这个错误

从网上找了很多办法,其中最为简单的是将compression.request.enabled = false,compression.response.enabled = false ,这样问题也能解决,但公司的架构师认为这样太粗暴,不够友好.....于是又找另外的解决方法

  compression:
    request:
      enabled: true
      # 配置压缩支持的 MIME TYPE
      mime-types: text/xml,application/xml,application/json 
      # 配置压缩数据大小的下限
      min-request-size: 2048 
    response:
      enabled: true

第二种方法:将min-request-size: 2048的大小设置大一些。这个单位是b。也就是说,当参数小于这个压缩数据大小的下限时,会将传递的参数压缩,而在压缩的过程中,出现了乱码,另一个模块接收时报错了。将这个下限设置高,传递的参数可以更多,有点投机取巧的意思。不完美,在大佬的建议下,又找到第三种方法,如下:

# 配置压缩数据大小的下限

min-request-size: 2048

第三种方法:原有的配置不变,原来spring cloud模块之间的调用,他有自己原生的方法,不是okhttp,httpclient,具体的自己去查。在排查的过程中发现,httpclient的包没有引用到使用到的模块下,所以报错。所以需要引用如下包问题解决。

# feign 配置
feign:
  sentinel:
    enabled: true
  okhttp:
    enabled: false
  httpclient:
    enabled: true
  client:
    config:
      default:
        connectTimeout: 10000
        readTimeout: 10000
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

第四种办法:将feign.okhttp.enabled = true,feign.httpclient.enabled = false

通过引用okhttp的方法,也能解决

       <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-okhttp</artifactId>
        </dependency>

增加拦截器动态删除Accept-Encoding 参数,使okhttp压缩生效

@Slf4j
public class HttpOkInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
 
        Request originRequest = chain.request();
        Response response = null;
        if (StringUtils.isNotEmpty(originRequest.header("Accept-Encoding"))) {
            Request request = originRequest.newBuilder().removeHeader("Accept-Encoding").build();
 
            long doTime = System.nanoTime();
            response = chain.proceed(request);
            long currentTime = System.nanoTime();
            if(response != null) {
                ResponseBody responseBody = response.peekBody(1024 * 1024);
                LogUtil.info(log, String.format("接收响应: [%s] %n返回json:【%s】 %.1fms%n%s",
                        response.request().url(),
                        responseBody.string(),
                        (currentTime - doTime) / 1e6d,
                        response.headers()));
            }else {
                String encodedPath = originRequest.url().encodedPath();
                LogUtil.info(log, String.format("接收响应: [%s] %n %.1fms%n",
                        encodedPath,
                        (currentTime - doTime) / 1e6d));
            }
        }
 
        return response;
    }
 
}

fegin配置类

@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignOkHttpConfig {
 
    @Bean
    public okhttp3.OkHttpClient okHttpClient(){
        return new okhttp3.OkHttpClient.Builder()
                //设置连接超时
                .connectTimeout(10, TimeUnit.SECONDS)
                //设置读超时
                .readTimeout(10, TimeUnit.SECONDS)
                //设置写超时
                .writeTimeout(10, TimeUnit.SECONDS)
                //是否自动重连
                .retryOnConnectionFailure(true)
                .connectionPool(new ConnectionPool(10, 5L, TimeUnit.MINUTES))
                .build();
 
    }
 
 
}

 综上:上面的四种方法我都试过,都能成功,第一种比较暴力,推荐使用第三种,第四种,完美解决这个问题

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值