SpringBoot HTTP 400排查方式

 更新时间:2024年08月10日 08:47:38   作者:Soulic  
这篇文章主要介绍了SpringBoot HTTP 400排查方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

背景

前段时间朋友咨询他们公司某个HTTP接口偶现400错误,有没有什么好的分析方法和解决方案,使用的是Spring Cloud体系。最近有时间总结下这个问题的处理过程。

为了分析问题,笔者使用 Spring Boot 3.0.2还原报错场景进行讲解。

问题分析

从朋友反馈的情况看,返回400状态错误码的接口并不是一直出错,出错的概率在5%左右,得出并不是系统的错误,从状态码400来看是调用方出错了,请求头或者请求参数错误。

从服务器上查tomcat的错误日志,找到类似下图的错误。

Tomcat日志

从错误日志看到,调用方的请求头个数超过了Tomcat默认设置的个数(100个)。

定位

根据以上分析,需要在服务器上抓包,看调用方到底使用了什么参数。

在服务器上使用 tcpdump工具抓包分析http请求具体信息来 定位问题。

因为不能从服务器上下载文件,使用如下命令查看http请求信息。

tcpdump -A -s0 port 8080

在服务器上查看到类似如下的http请求信息,通过Header信息发送是使用的某个链路追踪工具添加的链路调用请求信息,每经过一次调用就会添加一个同名的Header,调用链路多了的话就会导致Header个数超过Tomcat的默认值,从而导致Tomcat抛出400错误。

以下是使用Postman模拟超过100个Header的请求日志信息中的部分。

tcppdump日志

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

如果可以下载文件的话,使用下面的命令抓包,在开发机上使用wireshark工具分析http请求包信息是最好的。

sudo tcpdump  port 8080 -w http.400.cap

Wireshark

解决方案

找到问题原因之后,就好解决了。

解决方案有两种:

  • 找链路追踪工具的团队解决Header的问题
  • 设置Tomcat Header个数

由于不是本公司系统且需要及时解决该问题,没办法解决链路追踪工具的问题,给朋友推荐自定义配置的方式设置Tomcat最大Header数量,代码如下:

/**
 * 自定义Tomcat配置参数
 */
@ConditionalOnProperty(value = {"server.tomcat.max-header-enable"}, havingValue = "true", matchIfMissing = false)
public class TomcatConfigure {
    /**
     * 最大Header数量
     */
    @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);
            }
        };
    }
}

在应用启动参数上加

**-Dserver.tomcat.max-header-enable=true -Dserver.tomcat.max-header-count=200**

重启服务后解决该问题。

总结

在这个故障排查过程中,需要对HTTP协议有较深的掌握,对HTTP状态、请求头等非常熟悉;熟练使用一些网络工具,如tcpdump、wireshark等。

在解决过程中需要开发人员熟练使用Spring Boot(有源码经验最好),这样可以对Spring Boot做扩展,给需要的组件做个性化定制开发。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Spring Hibernate实现分页功能

    Spring Hibernate实现分页功能

    这篇文章主要为大家详细介绍了Spring Hibernate实现分页功能的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • java中throws与try...catch的区别点

    java中throws与try...catch的区别点

    在本篇文章里小编给大家整理了一篇关于java中throws与try...catch的区别点的内容,需要的朋友们跟着学习下。
    2020-02-02
  • springboot+mybatis+redis 二级缓存问题实例详解

    springboot+mybatis+redis 二级缓存问题实例详解

    Mybatis默认没有开启二级缓存,需要在全局配置(mybatis-config.xml)中开启二级缓存。本文讲述的是使用Redis作为缓存,与springboot、mybatis进行集成的方法。需要的朋友参考下吧
    2017-12-12
  • Spring中Bean的生命周期实例讲解

    Spring中Bean的生命周期实例讲解

    这篇文章主要介绍了Spring中Bean的生命周期讲解,而Spring中的一个Bean从开始到结束经历很多过程,但总体可以分为六个阶段Bean定义、实例化、属性赋值、初始化、生存期、销毁,需要的朋友可以参考下
    2023-08-08
  • 解决springboot运行出现错误:找不到或无法加载主类com.xxxx.xxxx.Application问题

    解决springboot运行出现错误:找不到或无法加载主类com.xxxx.xxxx.Application问题

    文章介绍了在服务器上运行一个未使用的Java项目时遇到的“找不到或无法加载主类”错误,并提供了两种解决方法:通过Maven install或build …、Goals输入install并跳过测试来重新构建项目
    2024-11-11
  • Java编译生成多个.class文件的原理和作用

    Java编译生成多个.class文件的原理和作用

    作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象
    2025-04-04
  • druid执行SQL出现错误但不影响返回结果的问题及解决

    druid执行SQL出现错误但不影响返回结果的问题及解决

    这篇文章主要介绍了druid执行SQL出现错误但不影响返回结果的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • springboot使用redisTemplate操作lua脚本

    springboot使用redisTemplate操作lua脚本

    本文主要介绍了springboot使用redisTemplate操作lua脚本,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • java swing实现贪吃蛇双人游戏

    java swing实现贪吃蛇双人游戏

    这篇文章主要为大家详细介绍了java swing实现贪吃蛇双人小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01
  • scala 操作数据库的方法

    scala 操作数据库的方法

    这篇文章主要介绍了scala 操作数据库的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-06-06

最新评论