Spring?Boot中的max-http-header-size配置方式
關(guān)于max-http-header-size配置
概述
默認(rèn)情況下,Spring Boot Web 應(yīng)用程序包括一個(gè)預(yù)配置的嵌入式 Web 服務(wù)器。但是,在某些情況下,我們希望修改默認(rèn)配置以滿足自定義要求。
在本教程中,講解如何在 Spring Boot 2.x 應(yīng)用程序的application.properties文件中對(duì)請(qǐng)求標(biāo)頭進(jìn)行設(shè)置和使用max-http-header-size屬性。
Max-HTTP-Header-Size
Spring Boot 支持Tomcat、Undertow和Jetty作為嵌入式服務(wù)器。通常,我們?cè)?Spring Boot 應(yīng)用程序中的application.properties文件或application.yaml文件中進(jìn)行服務(wù)器配置。
大多數(shù) Web 服務(wù)器都有自己的一組 HTTP 請(qǐng)求header大小限制。HTTP header值受服務(wù)器實(shí)現(xiàn)的限制。在 Spring Boot 應(yīng)用程序中,最大 HTTP header大小是使用server.max-http-header-size 配置的。Tomcat和Jetty的實(shí)際默認(rèn)值為8kB,Undertow的默認(rèn)值為1MB。
要修改最大 HTTP header大小,在application.properties文件中進(jìn)行如下配置:
server.max-http-header-size=1024000
從 Spring Boot 2.1 開始,可使用DataSize可解析值:
server.max-http-header-size=10KB
請(qǐng)求頭太大
假設(shè)發(fā)送的請(qǐng)求的總 HTTP header大小大于max-http-header-size值。服務(wù)器以“400 Bad request”錯(cuò)誤拒絕請(qǐng)求。在下一個(gè)示例中,我們將在日志文件中看到此錯(cuò)誤。
讓我們創(chuàng)建一個(gè)控制器,它有一個(gè)名為 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
當(dāng)我們?cè)趖oken中傳遞一個(gè)大小大于 8kb的字符串值時(shí),得到 400 錯(cuò)誤,如下所示:
max-http-header-size配置不合理導(dǎo)致OOM問題排查
#線上max-http-header-size導(dǎo)致oom問題排查
1. 首先線上vm參數(shù)配置-XX:+HeapDumpOnOutOfMemoryError
線上oom后會(huì)生成java_pidxxx.hprof文件
2. 使用Jprofiler分析下占用最大的空間是 char[]數(shù)組
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導(dǎo)致的了
5. 查看char[]里面具體內(nèi)容
不難發(fā)現(xiàn)數(shù)組后面大部分元素都是0
6. 綜合上述情況,可以得出一下結(jié)論
- OOM是因?yàn)榉峙湔?qǐng)求頭太大導(dǎo)致的
- 分配的char[]數(shù)組大部分空間都未使用到
7. 為什么會(huì)分配那么大的請(qǐng)求頭?是否和某個(gè)配置相關(guān)嗎?
排查配置發(fā)現(xiàn)
server: max-http-header-size: 10485760 #10M,值太大,并發(fā)量一上來服務(wù)就內(nèi)存溢出了 # max-http-header-size單位為字節(jié),默認(rèn)值為8*1024字節(jié)=8kb
修改配置前和修改后再次壓測(cè),修改后發(fā)現(xiàn)不會(huì)有這種情況了。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java計(jì)算兩個(gè)漢字相似度的實(shí)現(xiàn)方法
有時(shí)候我們希望計(jì)算兩個(gè)漢字的相似度,比如文本的 OCR 等場(chǎng)景,用于識(shí)別糾正,本文給大家詳細(xì)介紹了Java計(jì)算兩個(gè)漢字相似度的實(shí)現(xiàn)方法,文中有詳細(xì)的實(shí)現(xiàn)代碼,需要的朋友可以參考下2023-11-11spring boot使用自定義的線程池執(zhí)行Async任務(wù)
這篇文章主要介紹了spring boot使用自定義的線程池執(zhí)行Async任務(wù)的相關(guān)資料,需要的朋友可以參考下2018-02-02Spring bean對(duì)象實(shí)例化實(shí)現(xiàn)過程圖解
這篇文章主要介紹了Spring bean對(duì)象實(shí)例化實(shí)現(xiàn)過程圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07Spring boot定時(shí)任務(wù)的原理及動(dòng)態(tài)創(chuàng)建詳解
這篇文章主要給大家介紹了關(guān)于Spring boot定時(shí)任務(wù)的原理及動(dòng)態(tài)創(chuàng)建的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03Java8中方便又實(shí)用的Map函數(shù)總結(jié)
java8之后,常用的Map接口中添加了一些非常實(shí)用的函數(shù),可以大大簡(jiǎn)化一些特定場(chǎng)景的代碼編寫,提升代碼可讀性,快跟隨小編一起來看看吧2022-11-11