Nginx高并发下的优化

写在前面

最近在进行服务器的优化,正好在看nginx相关的知识,因此把一些知识整理一下。参考资料为《Nginx高性能web服务器详解》,建议你们都去读读这本书。
个人机器为四核CPU,16G内存。javascript

内核参数优化

把以下的参数追加到Linux系统的/etc/sysctl.conf文件中,而后使用以下命令使修改生效:/sbin/sysctl -pcss

net.core.netdev_max_backlog = 262144
net.core.somaxconn = 262144
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1

net.core.netdev_max_backlog参数

参数net.core.netdev_max_backlog,表示当每一个网络接口接受数据包的速率比内核处理这些包的速率快时,容许发送队列的数据包的最大数目,咱们调整为262144.java

net.core.somaxconn

该参数用于调节系统同时发起的TCP链接数,通常默认值为128,在客户端高并发的请求的状况下,该默认值较小,可能致使链接超时或者重传问题,咱们能够根据实际状况结合并发数来调节此值。node

net.ipv4.tcp_max_orphans

该参数用于设定系统中最多容许存在多少TCP套接字不被关联到任何一个用户文件句柄上,若是超过这个数字,没有与用户文件句柄关联到TCP套接字将当即被复位,同时发出警告信息,这个限制只是为了简单防治Dos攻击,通常系统内存充足的状况下,能够增大这个参数。linux

net.ipv4.tcp_max_syn_backlog

该参数用于记录还没有收到客户端确认信息的链接请求的最大值,对于拥有128内存的系统而言,此参数的默认值为1024,对小内存的系统则是128,通常在系统内存比较充足的状况下,能够增大这个参数的赋值。nginx

net.ipv4.tcp_timestamps

该参数用于设置时间戳,这个能够避免序列号的卷绕,在一个1Gb/s的链路上,遇到之前用过的序列号几率很大,当此值赋值为0时,警用对于TCP时间戳的支持,默认状况下,TCP协议会让内核接受这种异常的数据包,针对Nginx服务器来讲,建议将其关闭。web

net.ipv4.tcp_synack_retries

该参数用于设置内核放弃TCP链接以前向客户端发送SYN+ACK包的数量,为了创建对端的链接服务,服务器和客户端须要进行三次握手,第二次握手期间,内核须要发送SYN并附带一个回应前一个SYN的ACK,这个参数主要影响这个过程,通常赋予值为1,即内核放弃链接以前发送一次SYN+ACK包。编程

net.ipv4.tcp_syn_retries

该参数的做用与上一个参数相似,设置内核放弃创建链接以前发送SYN包的数量,赋值为1。json

nginx优化

nginx的配置文件以下:后端

user www-data;
pid /run/nginx.pid;

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 {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 60 50;
        send_timeout 10s;
        types_hash_max_size 2048;
        client_header_buffer_size 4k;
        client_max_body_size 8m;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;
        gzip_disable "msie6";
        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;


        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

worker_processes

worker_processes用来设置Nginx服务的进程数。推荐是CPU内核数或者内核数的倍数,推荐使用CPU内核数,由于个人CPU为4核的,因此设置为4。

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

设置一个进程理论容许的最大链接数,理论上越大越好,但不能够超过worker_rlimit_nofile的值。还有个问题,linux系统中有个指令open file resource limit,它设置了进程能够打开的文件句柄数量,能够用下面的指令查看你的linux系统中open file resource limit指令的值,cat /proc/sys/fs/file-max
能够将该指令设置为23900251
echo "2390251" > /proc/sys/fs/file-max; sysctl -p

worker_rlimit_nofile

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

use epoll

设置事件驱动模型使用epoll。事件驱动模型有select、poll、poll等。

  • select先建立事件的描述符集合,对于一个描述符,能够关注其上面的Read事件、Write事件以及Exception事件,因此要建立三类事件描述符集合,分别用来处理Read事件的描述符、Write事件的描述符、Exception事件的描述符,而后调用底层的select()函数,等待事件发生,轮询全部事件描述符集合的每个事件描述符,检查是否有事件发生,有的话就处理。select效率低,主要是轮询效率低,并且还要分别轮询三个事件描述符的集合。
  • poll方法与select相似,都是先建立一个关注事件的描述符集合,再去等待这些事件发生,而后再轮询描述符集合,检查有无事件发生,若是有,就去处理。不一样点是poll为Read事件、Write事件以及Exception事件只建立一个集合,在每一个描述符对应的结构上分别设置Read事件、Write事件以及Exception事件。最后轮询的时候,能够同时检察权这三个事件是否发生。能够说,poll库是select库的优化实现。
  • epoll是Nginx支持的高性能事件驱动库之一。是公认的很是优秀的事件驱动模型。和poll库跟select库有很大的不一样,最大区别在于效率。咱们知道poll库跟select库都是建立一个待处理的事件列表,而后把这个列表发给内核,返回的时候,再去轮询检查这个列表,以判断事件是否发生。这样在描述符多的应用中,效率就显得比较低下了。一种比较好的方式是把列表的管理交由内核负责,一旦某种事件发生,内核就把发生事件的描述符列表通知给进程,这样就避免了轮询整个描述符列表。首先,epoll库经过相关调用同志内核建立一个有N个描述符的事件列表,而后给这些描述符设置所关注的事件,并把它添加到内核的事件列表中去。完成设置之后,epoll库就开始等待内核通知事件发生了,某一事件发生后,内核讲发生事件的描述符列表上报给epoll库,获得事件列表的epoll库,就能够进行事件处理了。epoll库在linux平台是高效的,它支持一个进程打开大数目的事件描述符,上限是系统能够打开文件的最大数目;同时,epoll库的IO效率不随描述符数量的增长而线性降低,由于它只会对内核上报的活跃的描述符进行操做。

accept_mutex

这个牵扯到《UNIX网络编程》第一卷中提到的“惊群”问题(Thundering herd problem),大体意思是当某一时刻只有一个网络链接到来时,多个睡眠进程会被同时叫醒,但只有一个进程可得到链接,若是每次唤醒的进程数目太多,会影响一部分系统性能。在Nginx服务器的多进程下,就可能出现这个问题,为了解决这个问题,Nginx配置了包含这样一条指令accept_mutex,当其设置为开启的时候,将会对多个Nginx进程接受链接进行序列化,防止多个进程对链接的争抢。当服务器链接数很少时,开启这个参数会让负载有必定程度的下降。可是当服务器的吞吐量很大时,为了效率,请关闭这个参数;而且关闭这个参数的时候也可让请求在多个worker间的分配更均衡。因此咱们设置accept_mutex off;

multi_accept

sendfile

使用开启或关闭是否使用sendfile()传输文件,普通应用应该设为on,下载等IO重负荷的应用应该设为off,由于大文件不适合放到buffer中。
传统文件传输中(read/write方式)在实现上3实际上是比较复杂的,须要通过屡次上下文切换,当须要对一个文件传输时,传统方式是:

  • 调用read函数,文件数据被copy到内核缓冲区
  • read函数返回,数据从内核缓冲区copy到用户缓冲区
  • write函数调用,将文件数据从用户缓冲区copy到内核与socket相关的缓冲区
  • 数据从socket缓冲区copy到相关协议引擎

从上面能够看出来,传统readwrite进行网络文件传输的方式,在过程当中经历了四次copy操做。
硬盘->内核buffer->用户buffer->socket相关缓冲区->协议引擎
而sendfile系统调用则提供了一种减小屡次copy,提升文件传输性能的方法。流程以下:

  • sendfile系统效用,文件数据被copy至内核缓冲区
  • 记录数据文职和长度相关的数据保存到socket相关缓存区
  • 实际数据由DMA模块直接发送到协议引擎

tcp_nopush

sendfile为on时这里也应该设为on,数据包会累积一下再一块儿传输,能够提升一些传输效率。

tcp_nodelay

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

keepalive_timeout

HTTP链接的持续时间。设的太长会使无用的线程变的太多。这个根据本身服务器访问数量、处理速度以及网络情况方面考虑。

send_timeout

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

types_hash_max_size

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

client_header_buffer_size

该指令用于设置Nginx服务器容许的客户端请求头部的缓冲区大小,默认为1KB,此指令的赋值能够根据系统分页大小来设置,分页大小能够用如下命令获取getconf PAGESIZE

client_max_body_size 8m

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

gzip on

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

gzip_disable

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

gzip_min_length

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

gzip_comp_level

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

gzip_vary

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

gzip_buffers;

该指令用于设置Gzip压缩文件使用存储空间的大小,
语法gzip_buffers number size;number,指定Nginx服务器须要向系统申请存储空间的个数,size,指定每一个缓存空间的大小。根据配置项,Nginx服务器在对响应输出数据进行Gzip压缩时需向系统申请numbersize大小的空间用于存储压缩数据。默认状况下,numbersize的值为128,其中size的值为系统内存页一页的大小,用getconf PAGESIZE来获取

gunzip_static

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

gzip_types

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

相关文章
相关标签/搜索