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;
}
为这篇文章评分
[Total: 15 Average: 4.3]

3 Responses to “Nginx性能优化之配置缓冲、超时、压缩和日志

  • theobob cool
    7 years ago

    不错的帖子

  • Gertrude Libertini
    6 years ago

    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.

  • 很好,学到了

Leave a Reply

Your email address will not be published.

The maximum upload file size: 2 MB. You can upload: image, audio, video, document, spreadsheet, interactive, text, archive, code, other. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here