Feign 400错误引发的一系列问题

Feign 400错误引发的一系列问题

问题介绍

在使用Feign进行远程调用的时候出现非常奇怪的400错误,错误信息大概如下:

feign.FeignException: status 400 reading

并且还带有2个非常奇怪的问题:

  1. 一个前端请求接口,到达后端的时候会发起2次相同的Feign远程调用,但第一次成功,但是第二次会失败,错误信息如上。
  2. 一个前端请求接口,达到后端的时候调用Feign接口的时候会卡死。

问题定位

通过开启debug模式,查看输出日志发现,2个Feign接口都调用成功了,但是第二个接口的数据被第一个接口给截断了,导致第二个接口返回的数据不够完整。

此时,思绪万千,百思不得其解,想到http协议的content-length是用来确定请求体长度的,难道是这个问题导致?

因此,立马查看HTTP协议的content-length头部信息,果然不出我所料,问题就在这里。这里需要介绍2个http头部,就是connection头部和content-length头部,当2这结合起来的时候会有一些意想不到的结果。

Http请求头:connection、content-length

当connection头部为:keep-alive,就是http客户端告知http服务端,我们一直使用保持连接,不要关闭该连接,后面的请求也复用该连接,因为每次建立tcp连接是一件比较耗时的事情。那么,当客户端与服务器协商好了使用keep-alive的时候,就需要一个机制来区分每个http请求了,这个时候content-length就很重要了,这个头部可以确定每个请求体的长度,从而可以确定每个请求的长度,这样http服务端就可以区分每个请求,从而不到引起数据混乱。

问题解决

明白了Http协议中connection和content-length头部的作用,此时来检查feign调用是否存在这个问题。通过排查,缺失存在该问题。因为项目中为了共用页面发送的Authorization头部,用来保持所有远程调用使用统一的认证信息,因此需要在feign中传递该头部。但是实际操作的时候将前端发送过来的所有头部都传递下去了,就导致所有feign接口都共用了前端的头部信息,因此就导致了一系列的问题。因此,在使用feign的时候一定要小心http头部共用,只有共用需要的头部信息,不要无脑的将所有的头部信息都共用给feign接口,否则就会出现很多意想不到的问题。

这里解决了问题1,回过头来想想问题2,为什么有时候会出现卡死的现象呢?

这还需要我们从http协议出发来看待问题,当我们共用了前端发来的keep-alive和content-length请求头后,如果feign实际响应内容的长度达不到content-length的时候,那么此时,feign客户端会一直等待,直到feign服务端的数据达到content-length的长度要求,因此就会出现卡死现象了。

问题总结

这个问题花费了我很长时间定位,因此记录下来并好好总结,防止以后犯类似的问题。解决问题的过程确实可以学到很多,也学会了很多。主要总结下来有如下几点:

  1. 以前很少接触到http协议本身的问题,也不太了解http协议也会受到头部的影响,因此以后也要多多了解http协议,对于解决问题大有帮助;同理,我觉的开发也应该需要了解tcp/ip协议,否则当出现这些问题的时候也会有一定的解决能力。
  2. 以后再使用http头部的时候需要更加谨慎。
  3. 出现问题的时候需要冷静分析,知其然知其所以然,不要被问题表面现象蒙蔽。

不说了,大家国庆节快乐,跟祖国一起过节去了。

2021-10-2 12:18:58

深圳南山

上一篇:Oracle 字符串转多行(REGEXP_SUBSTR)


下一篇:微服务操作