目录
问题
- 通过监控ELK日志 线上出现如下错误
414 Request-URI Too Large
- 怀疑是GET参数太大导致URL过长
![](https://img.haomeiwen.com/i2180450/e9f4c93ed8ad4d7b.png)
- 于是尝试在本地环境复现上述问题
复现
Java
sudo apt install -y openjdk-8-jdk
curl -s get.sdkman.io | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install springboot 2.1.13.RELEASE
spring init -b 2.1.13.RELEASE -dweb --build gradle HelloSpring && cd HelloSpring
./gradlew bootrun
curl localhost:8080
# {"timestamp":"2020-07-28T11:22:33.995+0000","status":404,"error":"Not Found","message":"No message available","path":"/"}
Nginx
sudo apt install -y nginx
sudo vim /etc/nginx/sites-enabled/java.conf
server {
listen 80;
server_name 192.168.56.150.xip.io;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8080;
proxy_read_timeout 90;
}
}
sudo nginx -t
sudo nginx -s reload
- 测试脚本
vim request.sh
#!/bin/bash
url="http://192.168.56.150.xip.io?ids=1"
for i in {1000..3000}
do
url="${url},$i"
done
echo ${url}
curl ${url}
bash request.sh
<html>
<head>
<title>414 Request-URI Too Large</title>
</head>
<body bgcolor="white">
<center>
<h1>414 Request-URI Too Large</h1>
</center>
<hr>
<center>nginx/1.10.3 (Ubuntu)</center>
</body>
</html>
解决
Nginx
sudo vim /etc/nginx/nginx.conf
# large_client_header_buffers 4 512k;
sudo nginx -t
sudo nginx -s reload
bash request.sh
# java.lang.IllegalArgumentException: Request header is too large
<!doctype html>
<html lang="en">
<head>
<title>HTTP Status 400 – Bad Request</title>
</head>
<body>
<h1>HTTP Status 400 – Bad Request</h1>
</body>
</html>
Java
vim src/main/resources/application.properties
server.max-http-header-size=500000
./gradlew bootrun
bash request.sh
# {"timestamp":"2020-07-28T11:22:33.692+0000","status":404,"error":"Not Found","message":"No message available","path":"/"}
原理
Nginx
-
首先根据client_header_buffer_size分配Request Header的Buffer (默认1K bytes)
-
如果分配的Buffer无法容纳Request Header (通常都会小于1K bytes)
-
那么根据large_client_header_buffers分配新的Buffer (默认1K bytes)
-
如果分配的Buffer仍然无法容纳Request Header
-
那么就会返回错误 414 Request-URI 太长 / 400 请求出错
因此可以得到这两个影响Request Header Buffer的配置修改策略如下
-
如果请求中的Header都很大 那么应该增大client_header_buffer_size 因为能减少一次内存分配
-
如果请求中只有少量请求Header很大 那么应该增大large_client_header_buffers 因为能减少无谓的内存开销
Java
Key | Default Value | Description |
---|---|---|
server.max-http-header-size | 8KB | Maximum size of the HTTP message header. |
优化
- 方法1 拆分GET接口 参数分批并行访问
# 过去
GET params 1000
# 优化
[GET params 500, GET params 500] <= 并行
- 方法2 使用POST接口 参数放至Body传递
# 过去
GET params 1000
# 优化
POST params 1000 (body)
- 方法3 欢迎您的经验和留言
网友评论