Feign 400錯誤引發的一系列問題

小東/yb發表於2021-10-02

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

深圳南山

相關文章