记一次nginx因client_header_buffer_size和proxy_buffers配置导致的问题排查
1、问题背景:
前端需要进行图片上传,在一次版本优化后,根据客户要求取消了图片压缩,导致上传接口请求header徒增,nginx报错信息如下:
[warn] 60937#0: *34319 an upstream response is buffered to a temporary file /dev/shm/proxy/0/40/0000000400 while reading upstream,
2、导致的问题原因:
后台nginx配置如下:
client_header_buffer_size 32k; large_client_header_buffers 4 32k; proxy_buffer_size 32k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k;
由于header限制配置为32K,超过这个大小会进行拦截,导致nginx转发报错。
3、问题解决:
调整nginx配置
client_header_buffer_size 256k; large_client_header_buffers 4 256k; proxy_buffer_size 256k; proxy_buffers 16 256k; proxy_busy_buffers_size 1024k;
重新加载配置
./sbin/nginx -s reload
4、配置详解
通用的 HTTP 请求头相关的配置主要也是大小、超时时间等等。它们都可以配置在 http、server 下面。
client_header_buffer_size
用于设置读取客户端请求头部的缓冲容量。
client_header_buffer_size size;
默认值是 1k ,对于大多数请求,1K的缓冲足矣。但如果请求中含有的cookie很长,或者请求来自WAP的客户端,可能请求头不能放在1K的缓冲中。 如果从请求行,或者某个请求头开始不能完整的放在这块空间中,那么 Nginx 将按照 large_client_header_buffers 指令的配置分配更多更大的缓冲来存放。
proxy_buffers:定义缓冲区的数量和大小,本文设置为 16 个 256KB 的缓冲区。
proxy_buffer_size:设置用于存储响应头的缓冲区大小,这里设置为 1024KB。
proxy_busy_buffers_size:定义在缓冲区繁忙时可以使用的缓冲区大小,通常为 proxy_buffers 总大小的两倍。
这里和请求体不同的是,请求体会往文件里放,但请求头不会,不够了再根据其它配置申请更大的内存。毕竟请求头的内容再大也大不到像需要上传文件的请求体一样。最终它的配置其实不会导致什么影响,因为最终如果不够了它会根据 large_client_header_buffers 的配置进行申请分配,因此,我们紧接着就看看 large_client_header_buffers 的配置。
large_client_header_buffers
这个配置是设置读取客户端请求超大请求的缓冲最大 number(数量) 和每块缓冲的 size(容量) 。
large_client_header_buffers number size;
它的默认值是 4 8k 。条件包括这么几点:
HTTP 请求行的长度不能超过一块缓冲的容量,否则nginx返回错误414 (Request-URI Too Large)到客户端。
每个请求头的长度也不能超过一块缓冲的容量,否则nginx返回错误400 (Bad Request)到客户端。
(请求行+请求头) 的大小不能超过 32k(4 * 8k) 。
5、优化后的nginx配置(仅参考使用,根据不同环境调整):
http
{
include mime.types;
default_type application/octet-stream;
server_tokens off;
log_format main '$http_x_forwarded_for | $time_local | $status | $body_bytes_sent | $gzip_ratio | '
'$request_method | $scheme | $server_protocol | $server_name | $server_port | '
'$request_uri | $request_time | $content_length | $http_referer | $http_user_agent | '
'$remote_addr | $remote_port | $remote_user | $http_cookie | $hostname | '
'$upstream_status | $upstream_addr | $upstream_http_host | $upstream_response_time';
#charset utf-8;
server_names_hash_bucket_size 128;
client_header_buffer_size 256k;
large_client_header_buffers 4 256k;
client_max_body_size 300m;
sendfile on;
tcp_nopush on;
keepalive_timeout 180s;
tcp_nodelay on;
client_body_buffer_size 2048k;
fastcgi_intercept_errors on;
proxy_connect_timeout 90;
proxy_read_timeout 180;
proxy_send_timeout 180;
proxy_buffer_size 256k;
proxy_buffers 16 256k;
proxy_busy_buffers_size 1024k;
proxy_temp_file_write_size 256k;
proxy_intercept_errors on;
server_name_in_redirect off;
proxy_hide_header X-Powered-By;
proxy_ignore_client_abort on;
gzip on;
gzip_min_length 100;
gzip_buffers 4 256k;
gzip_http_version 1.0;
gzip_comp_level 9;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
gzip_vary on;
include domains/*;
}
下面整理了nginx日志中常见的 error 日志:
1.”upstream prematurely(过早的) closed connection”
请求uri的时候出现的异常,是由于upstream还未返回应答给用户时用户断掉连接造成的,对系统没有影响,可以忽略
2.”recv() failed (104: Connection reset by peer)”
(1)服务器的并发连接数超过了其承载量,服务器会将其中一些连接Down掉;
(2)客户关掉了浏览器,而服务器还在给客户端发送数据;
(3)浏览器端按了Stop
3.”(111: Connection refused) while connecting to upstream”
用户在连接时,若遇到后端upstream挂掉或者不通,会收到该错误
4.”(111: Connection refused) while reading response header from upstream”
用户在连接成功后读取数据时,若遇到后端upstream挂掉或者不通,会收到该错误
5.”(111: Connection refused) while sending request to upstream”
Nginx和upstream连接成功后发送数据时,若遇到后端upstream挂掉或者不通,会收到该错误
6.”(110: Connection timed out) while connecting to upstream”
nginx连接后面的upstream时超时
7.”(110: Connection timed out) while reading upstream”
nginx读取来自upstream的响应时超时
8.”(110: Connection timed out) while reading response header from upstream”
nginx读取来自upstream的响应头时超时
9.”(110: Connection timed out) while reading upstream”
nginx读取来自upstream的响应时超时
10.”(104: Connection reset by peer) while connecting to upstream”
upstream发送了RST,将连接重置
11.”upstream sent invalid header while reading response header from upstream”
upstream发送的响应头无效
12.”upstream sent no valid HTTP/1.0 header while reading response header from upstream”
upstream发送的响应头无效
13.”client intended to send too large body”
用于设置允许接受的客户端请求内容的最大值,默认值是1M,client发送的body超过了设置值
14.”reopening logs”
用户发送kill -USR1命令
15.”gracefully shutting down”
用户发送kill -WINCH命令
16.”no servers are inside upstream”
upstream下未配置server
17.”no live upstreams while connecting to upstream”
upstream下的server全都挂了
18.”SSL_do_handshake() failed”
SSL握手失败
19.”ngx_slab_alloc() failed: no memory in SSL session shared cache”
ssl_session_cache大小不够等原因造成
20.”could not add new SSL session to the session cache while SSL handshaking”
ssl_session_cache大小不够等原因造成