本文不讨论操作系统方面的优化,只讨论在Nginx层面能进行如何优化,以达到尽可能最优的性能。也为了能应付高并发的网络大流量的情况。

worker_processes

worker_processes用来设置Nginx服务的进程数。推荐是CPU内核数或者内核数的倍数,推荐使用CPU内核数

worker_cpu_affinity

默认情况下,Nginx的多个进程有可能跑在某一个CPU或CPU的某一核上,导致Nginx进程使用硬件的资源不均,因此绑定Nginx进程到不同的CPU上是为了充分利用硬件的多CPU多核资源的目的。
worker_cpu_affinity用来为每个进程分配CPU的工作内核,参数有多个二进制值表示,每一组代表一个进程,每组中的每一位代表该进程使用CPU的情况,1代表使用,0代表不使用。所以我们使用worker_cpu_affinity 0001 0010 0100 1000;来让进程分别绑定不同的核上。

worker_connections

默认的值是1024,设置一个进程理论允许的最大连接数,理论上越大越好,但不可以超过worker_rlimit_nofile的值。
linux系统中有个指令open file resource limit,它设置了进程可以打开的文件句柄数量,可以用下面的指令查看你的linux系统中open file resource limit指令的值:

cat /proc/sys/fs/file-max

可以将该指令设置为23900251

worker_rlimit_nofile

设置毎个进程的最大文件打开数。如果不设的话上限就是系统的ulimit –n的数字,一般为65535。

use epoll

Linux关键配置,允许单个线程处理多个客户端请求。
与apache类似,nginx针对不同的操作系统,有不同的事件模型:

  • 标准事件模型
    Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,nginx会选择select或poll
  • 高效事件模型
    • Kqueue:使用于 FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X. 使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。
    • Epoll: 使用于Linux内核2.6版本及以后的系统。
      /dev/poll:使用于 Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。
    • Eventport:使用于 Solaris 10. 为了防止出现内核崩溃的问题, 有必要安装安全补丁。

accept_mutex

当某一时刻只有一个网络连接到来时,多个睡眠进程会被同时叫醒,但只有一个进程可获得连接,如果每次唤醒的进程数目太多,会影响一部分系统性能。
在Nginx服务器的多进程下,就可能出现这个问题,为了解决这个问题,Nginx配置了包含这样一条指令accept_mutex,当其设置为开启的时候,将会对多个Nginx进程接受连接进行序列化,防止多个进程对连接的争抢。当服务器连接数不多时,开启这个参数会让负载有一定程度的降低。但是当服务器的吞吐量很大时,为了效率,请关闭这个参数;并且关闭这个参数的时候也可以让请求在多个worker间的分配更均衡。所以我们设置accept_mutex off;

multi_accept

告诉nginx收到一个新连接通知后接受尽可能多的连接,设置为on

sendfile

开启sendfile选项,使用内核的FD文件传输功能,这个比在用户态用read() + write()的方式更加高效。普通应用应该设为on,下载等IO重负荷的应用应该设为off,因为大文件不适合放到buffer中。

tcp_nopush

sendfile为on时这里也应该设为on,数据包会累积一下再一起传输,可以提高一些传输效率。

tcp_nodelay

小的数据包不等待直接传输。默认为on。
看上去是和tcp_nopush相反的功能,但是两边都为on时nginx也可以平衡这两个功能的使用。

keepalive_timeout

配置连接keep-alive超时时间,服务器将在超时之后关闭相应的连接,设的太长会使无用的线程变的太多。这个根据自己服务器访问数量、处理速度以及网络状况方面考虑,10-30之间即可。

send_timeout

设置Nginx服务器响应客户端的超时时间,这个超时时间只针对两个客户端和服务器建立连接后,某次活动之间的时间,如果这个时间后,客户端没有任何活动,Nginx服务器将关闭连接,将其设置为10s,Nginx与客户端建立连接后,某次会话中服务器等待客户端响应超过10s,就会自动关闭。,默认是 60 秒。

types_hash_max_size

types_hash_max_size影响散列表的冲突率。types_hash_max_size越大,就会消耗更多的内存,但散列key的冲突率会降低,检索速度就更快。types_hash_max_size越小,消耗的内存就越小,但散列key的冲突率可能上升。

client_header_buffer_size

客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
分页大小可以用命令getconf PAGESIZE 取得,可以将其设置为4k;

client_max_body_size 8m

客户端上传的body的最大值。超过最大值就会发生413(Request Entity Too Large)错误。默认为1m,最好根据自己的情况改大一点。

gzip

启用gzip,对响应数据进行在线实时压缩,减少数据传输量。

gzip_disable

Nginx服务器在响应这些种类的客户端请求时,不使用Gzip功能缓存应用数据,gzip_disable "msie6"对IE6浏览器的数据不进行GZIP压缩。

gzip_min_length

Gzip压缩功能对大数据的压缩效果明显,但是如果压缩很小的数据,可能出现越压缩数据量越大的情况,因此应该根据相应页面的大小,选择性开启或者关闭Gzip功能,建议将值设置为1KB。

gzip_comp_level

设置压缩程度,包括级别1到级别9,级别1表示压缩程度最低,压缩效率最高;级别9表示压缩程度最高,压缩效率最低,最费时间。设置为3-4即可。

gzip_vary

用于设置在使用Gzip功能时是否发送带有“Vary:Accept-Encoding”头域的响应头部,该头域的主要功能是告诉接收方发送的数据经过了压缩处理,开启后端效果是在响应头部Accept-Encoding: gzip,对于本身不支持Gzip的压缩的客户端浏览器是有用的。

gzip_buffers

该指令用于设置Gzip压缩文件使用存储空间的大小,
语法gzip_buffers number size。number指定Nginx服务器需要向系统申请存储空间的个数,size指定每个缓存空间的大小。根据配置项,Nginx服务器在对响应输出数据进行Gzip压缩时需向系统申请number,size大小的空间用于存储压缩数据。

gunzip_static

开启时,如果客户端浏览器不支持Gzip处理,Nginx服务器将返回解压后的数据,如果客户端浏览器支持Gzip处理,Nginx服务器忽略该指令设置。仍然返回压缩数据。

gzip_types

Nginx服务器可以根据MIME类型选择性开启Gzip压缩功能。该指令涌来设置MIME类型。

access logs

默认情况下,Nginx的每个请求都会记录在磁盘上的日志文件中,你可以使用这个方法进行统计,安全问题检查等, 带着这会在一定程度上带来IO使用成本. 如果你不打算用这些访问日志来做一些检查或其他用途, 你可以直接关闭它以避免对磁盘写操作, 但是如果你需要访问日志,你可以考虑保存日志到内存中.这将会比直接写到磁盘上快很多,并且明显减少IO的使用.

error logs

错误日志的等级参数你是可以指定的, 如果你指定的太低了他会记录404错误甚至是debug信息. 在实际的应用中可以将它设置为warn级别,将会是绰绰有余的并且能降低IO.

error_log /var/log/nginx/error.log crit;

告诉nginx只能记录严重的错误:

open file cache

从文件系统中读取文件由2部分组成,打开和关闭文件. 考虑到这是一个有阻塞的操作,因此不要忽略这部分. 因此, 对于我们来说缓存打开文件的描述符是非常好的

client_body_buffer_size

client_body_buffer_size指令用来指定处理客户端请求的缓冲区大小,?这个代表了访问请求的body. 这是用来处理POST的数据,也就是通过提交表单,文件上传等请求的数据. 如果你需要处理很多大的POST请求的,你必须确保缓存区要设置的足够大.

proxy_buffers

proxy_buffers的缓冲区大小一般会设置的比较大,以应付大网页。 proxy_buffers当中单个缓冲区的大小是由系统的内存页面大小决定的,Linux系统中一般为4k。 proxy_buffers由缓冲区数量和缓冲区大小组成的。总的大小为number*size。
若某些请求的响应过大,则超过_buffers的部分将被缓冲到硬盘(缓冲目录由_temp_path指令指定), 当然这将会使读取响应的速度减慢, 影响用户体验. 可以使用proxy_max_temp_file_size指令关闭磁盘缓冲.

proxy_buffer_size

后端服务器的相应头会放到proxy_buffer_size当中,这个大小默认等于proxy_buffers当中的设置单个缓冲区的大小。 proxy_buffer_size只是响应头的缓冲区,没有必要也跟着设置太大。 proxy_buffer_size最好单独设置,一般设置个4k就够了。

proxy_busy_buffers_size

proxy_busy_buffers_size不是独立的空间,他是proxy_buffersproxy_buffer_size的一部分。nginx会在没有完全读完后端响应的时候就开始向客户端传送数据,所以它会划出一部分缓冲区来专门向客户端传送数据(这部分的大小是由proxy_busy_buffers_size来控制的,建议为proxy_buffers中单个缓冲区大小的2倍),然后它继续从后端取数据,缓冲区满了之后就写到磁盘的临时文件中。

proxy_max_temp_file_size proxy_temp_file_write_size

临时文件由proxy_max_temp_file_size和proxy_temp_file_write_size这两个指令决定。 proxy_temp_file_write_size是一次访问能写入的临时文件的大小,默认是proxy_buffer_size和proxy_buffers中设置的缓冲区大小的2倍,Linux下一般是8k。
proxy_max_temp_file_size指定当响应内容大于proxy_buffers指定的缓冲区时, 写入硬盘的临时文件的大小. 如果超过了这个值, Nginx将与Proxy服务器同步的传递内容, 而不再缓冲到硬盘. 设置为0时, 则直接关闭硬盘缓冲.

proxy_buffering

proxy_buffering这个参数用来控制是否打开后端响应内容的缓冲区,如果这个设置为off,那么proxy_buffersproxy_busy_buffers_size这两个指令将会失效。 但是无论proxy_buffering是否开启,对proxy_buffer_size都是生效的。
proxy_buffering开启的情况下,nignx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端(边收边传,不是全部接收完再传给客户端)。 临时文件由proxy_max_temp_file_sizeproxy_temp_file_write_size这两个指令决定的。

如果proxy_buffering关闭,那么nginx会立即把从后端收到的响应内容传送给客户端,每次取的大小为proxy_buffer_size的大小,这样效率肯定会比较低。

注: proxy_buffering启用时,要提防使用的代理缓冲区太大。这可能会吃掉你的内存,限制代理能够支持的最大并发连接数。

server_tokens

server_tokens off;并不会让nginx执行的速度更快,但它可以关闭在错误页面中的nginx版本数字,这样对于安全性是有好处的。

client_header_timeout client_body_timeout

设置请求头和请求体(各自)的超时时间。我们也可以把这个设置低些。

reset_timeout_connection

告诉nginx关闭不响应的客户端连接。这将会释放那个客户端所占有的内存空间。

limit_conn_zone $binary_remote_addr zone

设置用于保存各种key(比如当前连接数)的共享内存的参数。5m就是5兆字节,这个值应该被设置的足够大以存储(32K5)32byte状态或者(16K5)64byte状态。

limit_conn

为给定的key设置最大连接数。这里key是addr,我们设置的值是100,也就是说我们允许每一个IP地址最多同时打开有100个连接。

gzip_proxied

允许或者禁止压缩基于请求和响应的响应流。我们设置为any,意味着将会压缩所有的请求。

gzip_static

gzip_static on ;告诉nginx在压缩资源之前,先查找是否有预先gzip处理过的资源。这要求你预先压缩你的文件,从而允许你使用最高压缩比,这样nginx就不用再压缩这些文件了

open_file_cache

这个将为打开文件指定缓存,默认是没有启用的,max 指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。打开缓存的同时也指定了缓存最大数目,以及缓存的时间。我们可以设置一个相对高的最大时间,这样我们可以在它们不活动超过20秒后清除掉。

open_file_cache_valid

这个是指多长时间检查一次缓存的有效信息。

open_file_cache_min_uses

open_file_cache指令中的inactive 参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive 时间内一次没被使用,它将被移除。定义了open_file_cache中指令参数不活动时间期间里最小的文件数。

open_file_cache_errors

指定了当搜索一个文件时是否缓存错误信息,也包括再次给配置中添加文件。我们也包括了服务器模块,这些是在不同文件中定义的。如果你的服务器模块不在这些位置,你就得修改这一行来指定正确的位置。

keepalive_requests

单个客户端在 keep-alive 连接上可以发送的请求数量,在测试环境中,需要配置个比较大的值。

最后,综上所述,配置文件如下:

worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
worker_rlimit_nofile 65535;

events {
        use epoll;
        worker_connections 65535;
        accept_mutex off;
        multi_accept off;
}

http {
       client_header_buffer_size 2k;
       large_client_header_buffers 4 4k;
       client_max_body_size 8m;
       
       open_file_cache max=204800 inactive=20s;
       open_file_cache_min_uses 1;
       open_file_cache_valid 30s;
       tcp_nodelay on;
       sendfile on;
       tcp_nopush on;
       tcp_nodelay on;
       keepalive_timeout 60;
       send_timeout 10s;
       types_hash_max_size 2048;
       client_header_buffer_size 4k;
       client_max_body_size 8m;
       server{
           location /{
               proxy_buffering on;
               proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
               proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的设置
               proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
               proxy_temp_file_write_size 64k;
           }
       }
       access_log /var/log/nginx/access.log;
       error_log /var/log/nginx/error.log;
       gzip on;
       gzip_disable "msie6";
       gzip_http_version 1.0;
       gzip_min_length 1024;
       gzip_vary on;
       gzip_comp_level 2;
       gzip_buffers 32 4k;
       gunzip_static on;
       gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    }
}