SpringBoot HTTP 400排查方式
背景
前段時間朋友咨詢他們公司某個HTTP接口偶現(xiàn)400錯誤,有沒有什么好的分析方法和解決方案,使用的是Spring Cloud體系。最近有時間總結(jié)下這個問題的處理過程。
為了分析問題,筆者使用 Spring Boot 3.0.2還原報錯場景進行講解。
問題分析
從朋友反饋的情況看,返回400狀態(tài)錯誤碼的接口并不是一直出錯,出錯的概率在5%左右,得出并不是系統(tǒng)的錯誤,從狀態(tài)碼400來看是調(diào)用方出錯了,請求頭或者請求參數(shù)錯誤。
從服務(wù)器上查tomcat的錯誤日志,找到類似下圖的錯誤。

從錯誤日志看到,調(diào)用方的請求頭個數(shù)超過了Tomcat默認(rèn)設(shè)置的個數(shù)(100個)。
定位
根據(jù)以上分析,需要在服務(wù)器上抓包,看調(diào)用方到底使用了什么參數(shù)。
在服務(wù)器上使用 tcpdump工具抓包分析http請求具體信息來 定位問題。
因為不能從服務(wù)器上下載文件,使用如下命令查看http請求信息。
tcpdump -A -s0 port 8080
在服務(wù)器上查看到類似如下的http請求信息,通過Header信息發(fā)送是使用的某個鏈路追蹤工具添加的鏈路調(diào)用請求信息,每經(jīng)過一次調(diào)用就會添加一個同名的Header,調(diào)用鏈路多了的話就會導(dǎo)致Header個數(shù)超過Tomcat的默認(rèn)值,從而導(dǎo)致Tomcat拋出400錯誤。
以下是使用Postman模擬超過100個Header的請求日志信息中的部分。

18:27:56.864393 IP 192.168.1.103.64156 > fedora.webcache: Flags [.], seq 1:1461, ack 1, win 513, length 1460: HTTP: GET / HTTP/1.1 E....b@...S....g...d.....'......P....=..GET / HTTP/1.1 Header0: 0 Header1: 1 Header2: 2 Header3: 3 Header4: 4 ... Header95: 95 Header96: 96 Header97: 97 Header98: 98 Header99: 99 User-Agent: PostmanRuntime/7.29.2 Accept: */* Postman-Token: f
如果可以下載文件的話,使用下面的命令抓包,在開發(fā)機上使用wireshark工具分析http請求包信息是最好的。
sudo tcpdump port 8080 -w http.400.cap

解決方案
找到問題原因之后,就好解決了。
解決方案有兩種:
- 找鏈路追蹤工具的團隊解決Header的問題
- 設(shè)置Tomcat Header個數(shù)
由于不是本公司系統(tǒng)且需要及時解決該問題,沒辦法解決鏈路追蹤工具的問題,給朋友推薦自定義配置的方式設(shè)置Tomcat最大Header數(shù)量,代碼如下:
/**
* 自定義Tomcat配置參數(shù)
*/
@ConditionalOnProperty(value = {"server.tomcat.max-header-enable"}, havingValue = "true", matchIfMissing = false)
public class TomcatConfigure {
/**
* 最大Header數(shù)量
*/
@Value("${server.tomcat.max-header-count:100}")
private int maxHeaderCount;
@Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> tomcatCustomizer() {
return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
@Override
public void customize(ConfigurableWebServerFactory factory) {
TomcatConnectorCustomizer customizer = new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
protocol.setMaxHeaderCount(maxHeaderCount);
}
};
((TomcatServletWebServerFactory) factory).addConnectorCustomizers(customizer);
}
};
}
}
在應(yīng)用啟動參數(shù)上加
**-Dserver.tomcat.max-header-enable=true -Dserver.tomcat.max-header-count=200**
重啟服務(wù)后解決該問題。
總結(jié)
在這個故障排查過程中,需要對HTTP協(xié)議有較深的掌握,對HTTP狀態(tài)、請求頭等非常熟悉;熟練使用一些網(wǎng)絡(luò)工具,如tcpdump、wireshark等。
在解決過程中需要開發(fā)人員熟練使用Spring Boot(有源碼經(jīng)驗最好),這樣可以對Spring Boot做擴展,給需要的組件做個性化定制開發(fā)。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
shiro整合springmvc配置靜態(tài)資源過濾方式
文章介紹了在Spring Boot + Spring MVC + Shiro + JSP項目中,如何正確配置靜態(tài)資源路徑以避免在引入Shiro過濾器后資源加載失敗的問題2026-03-03
java構(gòu)建Stream流的多種方式總結(jié)
Java?8引入了Stream流作為一項新的特性,它是用來處理集合數(shù)據(jù)的一種函數(shù)式編程方式,本文為大家整理了多種java構(gòu)建Stream流的方式,希望對大家有所幫助2023-11-11
淺析Java迭代器Iterator和Iterable的區(qū)別
Java語言中,Iterator和Iterable都是用來遍歷集合類數(shù)據(jù)結(jié)構(gòu)的接口,雖然它們有很多相似的地方,但在具體實現(xiàn)中卻有著一些不同之處,本文將詳細(xì)分析它們的區(qū)別,并提供相應(yīng)的代碼示例,需要的朋友可以參考下2023-07-07
SpringBoot注解@MapperScan的實現(xiàn)
@MapperScan是MyBatis和MyBatis-Plus提供的SpringBoot注解,用于自動掃描并注冊?Mapper?接口,使其能夠被?Spring?容器管理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-05-05
JAVAEE項目結(jié)構(gòu)以及并發(fā)隨想
每個代碼里面的工具都是工具,API是你最需要理解的,哪個好,哪個不好,沒有準(zhǔn)確答案。 一切皆對象,對于Java來講是純粹的,代理是對象,反射是對象,對象是對象,基本數(shù)據(jù)類型不是對象。2016-04-04
詳解Java使用sqlite 數(shù)據(jù)庫如何生成db文件
這篇文章主要介紹了詳解Java 操作sqllite 數(shù)據(jù)庫如何生成db文件的相關(guān)資料,需要的朋友可以參考下2017-07-07

