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

深圳南山

Tags: