Nginx性能优化之配置缓冲、超时、压缩和日志
Nginx的缓冲配置
请求缓冲在Nginx请求处理中扮演了重要的角色。当收到一条请求时,Nginx将请求写入缓冲当中。缓冲中的数据成为Nginx的变量,比如$request_body。如果缓冲容量比请求容量小,那么多出来的请求会被写入硬盘,这时便会有I/O操作。Nginx提供了多个directive来修改请求缓冲。
client_body_buffer_size
这个directive设定了request body的缓冲大小。如果body超过了缓冲的大小,那么整个body或者部分body将被写入一个临时文件。如果Nginx被设置成使用文件缓冲而不使用内存缓冲,那么这个dirctive就无效。client_body_buffer_size在32位系统上默认是8k,在64位系统上默认是16k。可以在http, server 和 location模块中指定,如下:
server { client_body_buffer_size 8k; }
client_max_body_size
这个directive设定Nginx可以处理的最大request body大小。如果收到的请求大于指定的大小,那么Nginx会回复HTTP 413错误(Request Entity too large)。如果web服务器提供大文件上传的话,那么设置好这个directive很重要。
Nginx默认为这个directive设定的值是1m,可以在http, server 和 location模块中定义,例如:
server { client_max_body_size 2m; }
client_body_in_file_only
启用这个directive会关闭Nginx的请求缓冲,将request body存储在临时文件当中,在http, server 和 location模块中定义。它可以有三个值:
- off: 禁止文件写入
- clean: request body将被写入文件,文件在请求处理完成后删除
- on: request body将被写入文件,但文件在请求处理完成后不会被删除
默认这个directive的值是off。我们可以将它设为off,例如:
http { client_body_in_file_only clean; }
这个directive对于错误调试很有用处,但并不建议在生产环境下使用它。
client_body_in_single_buffer
这个directive让Nginx将所有的request body存储在一个缓冲当中,它的默认值是off。启用它可以优化读取$request_body变量时的I/O性能。可以在http, server 和 location模块中定义。
server { client_body_in_single_buffer on; }
client_body_temp_path
这个directive指定存储request body的临时文件路径。另外,它可以指定目录层次。Nginx默认在Nginx的安装目录下面的client_body_temp子目录下面创建临时文件。这个directive可以在http, server 和 location 模块中定义。
server { client_body_temp_pathtemp_files 1 2; }
client_header_buffer_size
这个directive类似于client_body_buffer_size。它给request header分配缓冲。默认的值是1k,可以在http 和 server模块中定义。
http { client_header_buffer_size 1m; }
large_client_header_buffers
这个directive指定request header缓冲的数量和大小。只有当默认的缓冲不够用时,它才能被使用。当请求处理完成后或者连接进入keep-alive状态时,它被释放。可以在http 和 server模块中定义。
http { large_client_header_buffers 4 8k; }
如果请求的URI超过了单个缓冲的大小,那么Nginx会返回HTTP 414错误(Request URI Too Long)。如果有任何request header超过了单个缓冲的大小,那么Nginx会返回HTTP 400错误(Bad Request)。
Nginx的超时设置(timeout)
Nginx处理的每一个请求都会有相应的超时设置。如果做好这些超时的优化,就可以大大提升Nginx的性能。超时过后,系统资源被释放,用来处理其他的请求。下面,我们将讨论Nginx提供的多个关于超时的directive。
keepalive
HTTP是一种无状态的、基于请求+回复的协议。客户端打开一个TCP端口向服务器发送请求,服务器发送回复后断开完成的连接以释放服务器资源。
如果客户端向服务器发送多个请求,那么每个请求都要建立各自独立的连接以传输数据。在网页包含大量内容的情况下,这种方式变得效率低下,因为浏览器要为每一个内容打开一个连接。
HTTP有一个keepalive模式,keepalive告诉web服务器在处理完请求后保持TCP连接不断开。如果客户端发出另外一个请求,它可以利用这些保持打开的连接,而不必另外打开一个连接。当客户端感觉不再需要这些保持打开的连接时,或者web服务器发现经过一段时间(timeout)这些保持打开的连接没有任何活动,那么它们就会断开。浏览器一般会打开多个keepalive连接。
由于keepalive连接在一段时间内会保持打开状态,它们会在这段时间占用系统资源。如果web服务器流量大,而timeout的时间设置得过长,那么系统的性能会受到很大影响。
Nginx提供了多个可以用来设置keepalive连接的directive。
keepalive_timeout
这个directive用于设置keepalive连接的超时时间,默认为65秒。若将它设置为0,那么就禁止了keepalive连接。它在http, server 和 location模块中定义。
http { keepalive_timeout 20s; }
这个directive有另外一个可选的时间参数,例如:
http { keepalive_timeout 20s 18s; }
第二个参数18s被包含在回复header里。
curl -I http://www.example.com ........ Connection: keep-alive Keep-Alive: timeout=18 .....
keepalive_requests
这个directive设定了使用keepalive连接的请求数量上限。当使用keepalive连接的请求数量超过这个上限时,web服务器关闭keepalive连接。默认值为100,可以在http, server 和 location模块中定义。
http { keepalive_requests 20; }
keepalive_disabled
这条directive可以针对特定的浏览器关闭keepalive连接。默认值为msie6。可以在http, server 和 location模块中定义。
http { keepalive_disabled msie6 safari; }
send_timeout
这条directive指定了向客户端传输数据的超时时间。默认值为60秒,可以在http, server 和 location模块中定义。
server { send_timeout 30s; }
client_body_timeout
这条directive设定客户端与服务器建立连接后发送request body的超时时间。如果客户端在此时间内没有发送任何内容,那么Nginx返回HTTP 408错误(Request Timed Out)。它的默认值是60秒,在http, server 和 location模块中定义。
server { client_body_timeout 30s; }
client_header_timeout
这条directive设定客户端向服务器发送一个完整的request header的超时时间。如果客户端在此时间内没有发送一个完整的request header,那么Nginx返回HTTP 408错误(Request Timed Out)。它的默认值是60秒,在http 和 server模块中定义。
server { client_header_timeout 30s; }
Nginx的压缩配置(compression)
压缩可以减少服务器发送的数据包大小,从而加快了网页的加载速度。
ngx_http_gzip_module
Nginx的gzip压缩依赖于这个模块。服务器先压缩数据,然后将压缩后的数据发送给客户端。压缩的效果对于文本内容最明显,而gzip对于JPEG, GIF, MP3这些不可压缩的内容就没什么用处。另外,如果压缩水平太高,那么需要的CPU时间更多。ngx_http_gzip_module模块提供了下面的directive来配置gzip压缩。
gzip
这条directive可以Nginx启用gzip压缩功能,默认值为on,可以在http, server 和 location 以及if 当中定义。
http { gzip on; }
gzip_comp_level
这条directive设定gzip的压缩水平,压缩水平可以是1到9。太高的压缩水平对性能提升并没有太大好处,因为这需要更多的CPU时间。默认值是1,其中1到3是比较好的压缩水平,因为它们在最终的压缩数据大小和需要花费的CPU时间之间做出了很好的平衡。可以在http, server 和 location模块中定义。
http { gzip_comp_level 2; }
gzip_min_length
这条directive指定了压缩数据的最小长度,只有大于或等于最小长度才会对其压缩。它从Content-Length中获取数据的长度。默认值是20字节,在http, server 和 location中定义。
http { gzip_min_length 1000; }
gzip_types
这条directive指定了允许进行压缩的回复类型。默认值为text/html,在http, server 和 location中定义。
http { gzip_types text/html text/css text/plain; }
text/html类型总是会被压缩,text/html, text/css和text/plain这些是MIME类型。
gzip_http_version
这条directive指定一个HTTP版本。只有当请求的HTTP版本比这个版本更高或一样,Nginx才会压缩数据。默认值是1.1,在http, server 和 location模块中定义。
http { gzip_http_versioin 1.1; }
gzip_vary
这条directive可以在回复的header中添加Vary:Accept-Encoding这一栏。默认值是off,在http, server 和 location中定义。
http { gzip_vary on; }
gzip_disable
有些浏览器很弱智,比如IE6,它们看不懂gzip压缩后的数据。Nginx从请求header的User-Agent中确定浏览器,gzip_disable可以对弱智的浏览器关闭gzip压缩功能。在http, server, 和 location中定义。
http { gzip_disable "MSIE [1-6]\."; }
ngx_http_gzip_static_module
这个模块可以让Nginx发送一个已经压缩好的.gz文件,而不发送普通文件。Nginx并不会自己生成.gz文件,而是寻找是否有已经存在.gz文件。如果有,就发送那个.gz文件。这可以节省CPU时间。默认这个模块没有启用,可以在编译Nginx时加上–with-http_gzip_static_module选项来启用。下面是这个模块提供的directive。
gzip_static
这个就是让Nginx发送.gz压缩文件的directive。默认值是off。gzip_static的值设为on之后,Nginx会先判断客户端是否支持.gz文件,如果支持就发送.gz文件,不支持就发送普通文件。另外也可以将gzip_static的值设为always,这时Nginx总是发送.gz文件(如果.gz文件存在的话),而不会检查客户端是否支持.gz文件。
gzip_static也会查看gzip_http_version, gzip_proxied和gzip_disable的值来确定客户端是否支持压缩。它的值在http, server 和 location中定义。
server { gzip_static always; }
ngx_http_gunzip_module
这个模块让Nginx发送一个经解压的文件给那些不支持gzip的客户端,并且经常与ngx_http_gzip_static_module搭配使用。后者可以让Nginx发送一个已经压缩好文件,而前者可以解压文件以让Nginx发送给不支持压缩的客户端。这个模块默认没有启用,可以在编译Nginx时加上–with-http_gunzip_module选项来启用。
gunzip
这个directive用来解压.gz文件。默认值为off,在http, server 和 location当中定义。
location / { gzip_static always; gunzip on; }
Nginx的日志配置
日志是一把双刃剑。一方面,它提供了很多有用的信息;另一方面,它带来了计算成本。如果Nginx产生成千上万行日志,必然会对性能产生影响。下面来讨论优化日志的几个directive。
access_log
这条directive配置Nginx处理所有请求时产生的日志。它有多个参数,可以用来指定日志路径,日志格式样本,缓冲等等。syslog可以将日志传送给一个日志服务器而不写入日志文件。如果access_log的值设为off,那么Nginx不会产生任何日志。访问日志文件的默认路径是 /var/log/nginx/access.log。
http { access_log /var/log/nginx/access.log; }
error_log
Nginx默认启用了错误日志,error_log可以在http, server, location模块中定义。它可以有两个参数,第一个参数是错误日志的路径,第二个是错误日志的级别。级别的值可以是debug,info,notice,warn,error,crit,alert和emerg。
http { error_log /var/log/nginx/error.log crit; }
大综合
下面的配置综合了上述讨论的所有directive。
http { ###### # configuring buffers ###### client_body_buffer_size 15k; client_max_body_size 8m; #### # configuring timeouts #### keepalive_timeout 20; client_body_timeout 15; client_header_timeout 15; send_timeout 10; ###### # configuring gzip ###### gzip on; gzip_comp_level 2; gzip_min_length 1000; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; ##### # configuring logs ##### access_log off; log_not_found off; error_log logs/error.log crit; }
不错的帖子
Hi there! I simply wish to offer you a huge thumbs up for the great info you’ve got right here on this post. I am returning to your blog for more soon.
很好,学到了