当前位置 : 主页 > 编程语言 > java >

Spring Boot中的max-http-header-size配置方式

来源:互联网 收集:自由互联 发布时间:2023-01-30
目录 关于max-http-header-size配置 概述 Max-HTTP-Header-Size 请求头太大 max-http-header-size配置不合理导致OOM问题排查 1. 首先线上vm参数配置-XX:+HeapDumpOnOutOfMemoryError 2. 使用Jprofiler分析下占用最大的
目录
  • 关于max-http-header-size配置 
    • 概述
    • Max-HTTP-Header-Size
    • 请求头太大
  • max-http-header-size配置不合理导致OOM问题排查
    • 1. 首先线上vm参数配置-XX:+HeapDumpOnOutOfMemoryError
    • 2. 使用Jprofiler分析下占用最大的空间是 char[]数组
    • 3. 看下OOM栈信息
    • 4. 定位源码
    • 5. 查看char[]里面具体内容
    • 6. 综合上述情况,可以得出一下结论
    • 7. 为什么会分配那么大的请求头?是否和某个配置相关吗?

关于max-http-header-size配置 

概述

默认情况下,Spring Boot Web 应用程序包括一个预配置的嵌入式 Web 服务器。但是,在某些情况下,我们希望修改默认配置以满足自定义要求。

在本教程中,讲解如何在 Spring Boot 2.x 应用程序的application.properties文件中对请求标头进行设置和使用max-http-header-size属性。

Max-HTTP-Header-Size

Spring Boot 支持Tomcat、Undertow和Jetty作为嵌入式服务器。通常,我们在 Spring Boot 应用程序中的application.properties文件或application.yaml文件中进行服务器配置。

大多数 Web 服务器都有自己的一组 HTTP 请求header大小限制。HTTP header值受服务器实现的限制。在 Spring Boot 应用程序中,最大 HTTP header大小是使用server.max-http-header-size 配置的。Tomcat和Jetty的实际默认值为8kB,Undertow的默认值为1MB。

要修改最大 HTTP header大小,在application.properties文件中进行如下配置:

server.max-http-header-size=1024000

从 Spring Boot 2.1 开始,可使用DataSize可解析值:

server.max-http-header-size=10KB

请求头太大

假设发送的请求的总 HTTP header大小大于max-http-header-size值。服务器以“400 Bad request”错误拒绝请求。在下一个示例中,我们将在日志文件中看到此错误。

让我们创建一个控制器,它有一个名为 token 的header属性:

@RestController
@RequestMapping(value = "/request-header-test")
public class MaxHttpHeaderSizeController {
    @GetMapping
    public boolean testMaxHTTPHeaderSize(@RequestHeader(value = "token") String token) {
    return true;
    }
}

接下来,让我们向application.properties文件添加一些属性:

## Server connections configuration
server.tomcat.threads.max=200
server.connection-timeout=5s
server.max-http-header-size=8KB
server.tomcat.max-swallow-size=2MB
server.tomcat.max-http-post-size=2MB

当我们在token中传递一个大小大于 8kb的字符串值时,得到 400 错误,如下所示:

max-http-header-size配置不合理导致OOM问题排查

#线上max-http-header-size导致oom问题排查

1. 首先线上vm参数配置-XX:+HeapDumpOnOutOfMemoryError

线上oom后会生成java_pidxxx.hprof文件

2. 使用Jprofiler分析下占用最大的空间是 char[]数组

3. 看下OOM栈信息

// 这里把栈信息粘贴出来看一下
Thread dump at 27588:02.814.491
* Thread group "main":
  Thread "http-nio-51026-exec-115":
    at java.lang.OutOfMemoryError.<init>() (line: 48)
    at java.nio.HeapByteBuffer.<init>(int, int) (line: 57)
    at java.nio.ByteBuffer.allocate(int) (line: 335)
    at org.apache.coyote.http11.Http11OutputBuffer.<init>(org.apache.coyote.Response, int) (line: 110)
    at org.apache.coyote.http11.Http11Processor.<init>(org.apache.coyote.http11.AbstractHttp11Protocol, org.apache.coyote.Adapter) (line: 163)
    at org.apache.coyote.http11.AbstractHttp11Protocol.createProcessor() (line: 1001)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(org.apache.tomcat.util.net.SocketWrapperBase, org.apache.tomcat.util.net.SocketEvent) (line: 853)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun() (line: 1590)
    at org.apache.tomcat.util.net.SocketProcessorBase.run() (line: 49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (line: 1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run() (line: 624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run() (line: 61)
    at java.lang.Thread.run() (line: 748)

4. 定位源码

可以看到多半就是分配headerBufferSize导致的了

5. 查看char[]里面具体内容

不难发现数组后面大部分元素都是0

6. 综合上述情况,可以得出一下结论

  • OOM是因为分配请求头太大导致的
  • 分配的char[]数组大部分空间都未使用到

7. 为什么会分配那么大的请求头?是否和某个配置相关吗?

排查配置发现

server:
    max-http-header-size: 10485760 #10M,值太大,并发量一上来服务就内存溢出了
# max-http-header-size单位为字节,默认值为8*1024字节=8kb

修改配置前和修改后再次压测,修改后发现不会有这种情况了。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。

网友评论