首页>>后端>>SpringBoot->记一次SpringBoot SpringCloud 版本升级Feign调用抛出400错误问题

记一次SpringBoot SpringCloud 版本升级Feign调用抛出400错误问题

时间:2023-12-01 本站 点击:0

记一次SpringBoot SpringCloud 版本升级Feign调用抛出400错误问题

问题背景

公司新的项目使用SpringBoot2.5.5 SpringCloud Hoxton.SR9版本搭建, Feign的相关配置沿用的老项目SpringBoot2.1.18.RELEASE SpringCloud Greenwich.RELEASE版本的配置,  结果运行时Feign远程调用抛出400参数过长错误,  Feign调用的参数中包含大文本字段, 在老的项目中可以正常调用, 升级之后出现异常

Feign客户端使用的是POST+@RequestBody方式调用

Feign配置如下, 两个版本配置一样:

feign:client:  config:    default:      connect-timeout: 5000      read-timeout: 120000compression:  request:    enabled: true  response:    enabled: trueokhttp:  enabled: trueserver:max-http-header-size: 8192

排查过程

由于错误是在调用方抛出, 那基本上就是因为Feign在构造HttpConnection的过程中触发了这个错误, 我们可以发现升级之后feign-core的版本变更为10.10.1了, 我们只需要这个feign-core版本与之前的版本构造出来的请求有什么不同, 就能找出问题的原因了

找到feign客户端构造类feign.Feign.Builder#build, 从这个入口处开始断点跟踪调用链

相关代码如下:

public Feign build() {......SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,logLevel, decode404, closeAfterDecode, propagationPolicy, forceDecoding);......return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);}

根据上面的代码我们最终找到相关处理类feign.SynchronousMethodHandlerfeign.SynchronousMethodHandler#targetRequest 经过对此处代码的单步调试, 发现版本升级之后的fegin构造的request的headers多一个gzip相关的配置"Content-Encoding", feign.Client.Default#convertAndSend 相关代码:

HttpURLConnection convertAndSend(Request request, Options options) throws IOException {......// 这里获取出来的结果不一样// 2.5.5版本的可以获取到Collection<String> contentEncodingValues = request.headers().get(CONTENT_ENCODING);boolean gzipEncodedRequest =contentEncodingValues != null && contentEncodingValues.contains(ENCODING_GZIP);boolean deflateEncodedRequest =contentEncodingValues != null && contentEncodingValues.contains(ENCODING_DEFLATE);

boolean hasAcceptHeader = false; Integer contentLength = null; for (String field : request.headers().keySet()) { if (field.equalsIgnoreCase("Accept")) { hasAcceptHeader = true; } for (String value : request.headers().get(field)) { if (field.equals(CONTENT_LENGTH)) { // 导致这里的contentLength不同 if (!gzipEncodedRequest && !deflateEncodedRequest) { contentLength = Integer.valueOf(value); connection.addRequestProperty(field, value); } } else { connection.addRequestProperty(field, value); } } } // Some servers choke on the default accept string. if (!hasAcceptHeader) { connection.addRequestProperty("Accept", "/"); } if (request.body() != null) { if (disableRequestBuffering) { // 最终的connection设置不同的contentLength if (contentLength != null) { connection.setFixedLengthStreamingMode(contentLength); } else { connection.setChunkedStreamingMode(8196); } } ...... } return connection; }

## 总结根据上述分析, 我们发现导致400的最终原因是由于不同版本的默认压缩配置不同, 升级之后的版本删除请求压缩配置(`compression.request.enabled`), 即可正常调用
原文:https://juejin.cn/post/7102615499233558565


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/SpringBoot/6030.html