SpringBoot HTTP 400排查方式
背景
前段時(shí)間朋友咨詢他們公司某個(gè)HTTP接口偶現(xiàn)400錯(cuò)誤,有沒有什么好的分析方法和解決方案,使用的是Spring Cloud體系。最近有時(shí)間總結(jié)下這個(gè)問題的處理過程。
為了分析問題,筆者使用 Spring Boot 3.0.2還原報(bào)錯(cuò)場景進(jìn)行講解。
問題分析
從朋友反饋的情況看,返回400狀態(tài)錯(cuò)誤碼的接口并不是一直出錯(cuò),出錯(cuò)的概率在5%左右,得出并不是系統(tǒng)的錯(cuò)誤,從狀態(tài)碼400來看是調(diào)用方出錯(cuò)了,請求頭或者請求參數(shù)錯(cuò)誤。
從服務(wù)器上查tomcat的錯(cuò)誤日志,找到類似下圖的錯(cuò)誤。
從錯(cuò)誤日志看到,調(diào)用方的請求頭個(gè)數(shù)超過了Tomcat默認(rèn)設(shè)置的個(gè)數(shù)(100個(gè))。
定位
根據(jù)以上分析,需要在服務(wù)器上抓包,看調(diào)用方到底使用了什么參數(shù)。
在服務(wù)器上使用 tcpdump工具抓包分析http請求具體信息來 定位問題。
因?yàn)椴荒軓姆?wù)器上下載文件,使用如下命令查看http請求信息。
tcpdump -A -s0 port 8080
在服務(wù)器上查看到類似如下的http請求信息,通過Header信息發(fā)送是使用的某個(gè)鏈路追蹤工具添加的鏈路調(diào)用請求信息,每經(jīng)過一次調(diào)用就會添加一個(gè)同名的Header,調(diào)用鏈路多了的話就會導(dǎo)致Header個(gè)數(shù)超過Tomcat的默認(rèn)值,從而導(dǎo)致Tomcat拋出400錯(cuò)誤。
以下是使用Postman模擬超過100個(gè)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ā)機(jī)上使用wireshark工具分析http請求包信息是最好的。
sudo tcpdump port 8080 -w http.400.cap
解決方案
找到問題原因之后,就好解決了。
解決方案有兩種:
- 找鏈路追蹤工具的團(tuán)隊(duì)解決Header的問題
- 設(shè)置Tomcat Header個(gè)數(shù)
由于不是本公司系統(tǒng)且需要及時(shí)解決該問題,沒辦法解決鏈路追蹤工具的問題,給朋友推薦自定義配置的方式設(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é)
在這個(gè)故障排查過程中,需要對HTTP協(xié)議有較深的掌握,對HTTP狀態(tài)、請求頭等非常熟悉;熟練使用一些網(wǎng)絡(luò)工具,如tcpdump、wireshark等。
在解決過程中需要開發(fā)人員熟練使用Spring Boot(有源碼經(jīng)驗(yàn)最好),這樣可以對Spring Boot做擴(kuò)展,給需要的組件做個(gè)性化定制開發(fā)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Hibernate實(shí)現(xiàn)分頁功能
這篇文章主要為大家詳細(xì)介紹了Spring Hibernate實(shí)現(xiàn)分頁功能的相關(guān)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05java中throws與try...catch的區(qū)別點(diǎn)
在本篇文章里小編給大家整理了一篇關(guān)于java中throws與try...catch的區(qū)別點(diǎn)的內(nèi)容,需要的朋友們跟著學(xué)習(xí)下。2020-02-02springboot+mybatis+redis 二級緩存問題實(shí)例詳解
Mybatis默認(rèn)沒有開啟二級緩存,需要在全局配置(mybatis-config.xml)中開啟二級緩存。本文講述的是使用Redis作為緩存,與springboot、mybatis進(jìn)行集成的方法。需要的朋友參考下吧2017-12-12解決springboot運(yùn)行出現(xiàn)錯(cuò)誤:找不到或無法加載主類com.xxxx.xxxx.Application問題
文章介紹了在服務(wù)器上運(yùn)行一個(gè)未使用的Java項(xiàng)目時(shí)遇到的“找不到或無法加載主類”錯(cuò)誤,并提供了兩種解決方法:通過Maven install或build …、Goals輸入install并跳過測試來重新構(gòu)建項(xiàng)目2024-11-11druid執(zhí)行SQL出現(xiàn)錯(cuò)誤但不影響返回結(jié)果的問題及解決
這篇文章主要介紹了druid執(zhí)行SQL出現(xiàn)錯(cuò)誤但不影響返回結(jié)果的問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12springboot使用redisTemplate操作lua腳本
本文主要介紹了springboot使用redisTemplate操作lua腳本,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08java swing實(shí)現(xiàn)貪吃蛇雙人游戲
這篇文章主要為大家詳細(xì)介紹了java swing實(shí)現(xiàn)貪吃蛇雙人小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01