Nginx 的性能优化(性能调优)

摘要:nginx 的性能优化,nginx 最大连接数,worker_processes,worker_connections ,nginx 的 gzip 压缩,nginx 的工作模式,multi_accept ,expires 缓存设置。

Nginx 的性能优化(性能调优)

nginx 性能调优主要分为两部分,一部分是 linux 内核调优,比如积压队列、文件描述符、临时端口等。还有一部分是 nginx 配置调优,比如 worker 进程配置、nginx 的工作模式、nginx 的缓存、nginx 的返回限制、nginx 的压缩传输等等。


worker 进程配置

worker_processes – 是配置 worker 进程数量的,这个最佳值取决于很多因素,并不是说配置多少就是最佳的,应当根据服务器实际的性能和负载去配置一个合理的数值,如果你不知道如何配置一个合理的数值,那么设置成 auto 是最佳的(和系统 cpu 数量相等的数值)。

[root@localhost ~]# ps aux | grep nginx
root      1565  0.0  1.1  34636 11380 ?        Ss   10月15   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
www       1566  0.0  3.4  56060 34868 ?        S    10月15   0:00 nginx: worker process
root      9695  0.0  0.0 112736   992 pts/1    R+   20:35   0:00 grep --color=auto nginx

worker_cpu_affinity - 是将每个 worker 进程绑定到对应的 cpu 上面。

worker_processes  4;
worker_cpu_affinity 0001 0010 0100 1000;

也可以将第一个工作进程绑定到 cpu0 / cpu2,将第二个工作进程绑定到 cpu1 / cpu3。

worker_processes  2;
worker_cpu_affinity 0101 1010;

但是我们也可以将 worker_processes 和 worker_cpu_affinity 都设置成 auto 属性,这样在 nginx 版本 1.9.10 之后,是可以自动将 worker 进程绑定到对应的 cpu 上面的。

worker_processes  auto;
worker_cpu_affinity auto;

将 worker 进程绑定到对应的 cpu 上面,还有一个好处就是为了防止 cpu 上下文切换导致 cpu 缓存丢失,作为缓存丢失就要去访问本地内存,而 cpu 的跨核上下文切换是 cpu 上下文切换中影响最大的。


events 事件指令配置

events 指令模块设定 nginx 的工作模式及连接数上限。

events {
    use epoll;
    worker_connections 51200;
    multi_accept on;
    accept_mutex on;
}

use - 指令用来指定 nginx 的工作模式,nginx 支持的工作模式有 select、 poll、 kqueue、 epoll 、 rtsig 和/ dev/poll,不过 epoll 是最优的。当然也可以不指定事件处理模型,nginx 会自动选择最佳的事件处理模型。

use epoll;

worker_connections – 每个 worker 进程可以同时处理的最大连接数,默认值为 51200,这个值一般不用更改。但是该数目包括所有连接(例如,与代理服务器的连接等),而不仅包括与客户端的连接。另一个需要考虑的因素是,并发连接的实际数量不能超过打开文件最大数量的当前限制,可以通过 worker_rlimit_nofile 进行更改 。

worker_connections 51200;

利用 ulimit -n 命令查看当前系统打开的最大文件数量。可以看到当前系统的打开的最大文件数量是 65535,而默认的 51200 是小于这个值得,所以一般不同更改。

[root@localhost ~]# ulimit -n
65535

每个 worker 进程可以处理的最大并发量计算如下:从用户的角度讲,一次请求会并发两个链接,一个输入一个输出,所以这个值应该是 worker_connections * worker_processes/2 这么计算。但是如果 nginx 还要将请求发送到动态解释器去解析动态文件,所以这个最大并发数量应该是 worker_connections * worker_processes/4 这么计算。

multi_accept - 指令,一个 worker 进程尽可能的接收多个请求连接,如果被禁用了,那么每次只能接受一个新的连接。如果开启,一个 worker 进程可以同时接受所有的连接。如果使用 use 的时间类型是 kqueue 连接处理方法,则该 multi_accept 被忽略,因为该指令报告等待接受的新连接数。

multi_accept on;

accept_mutex - 指令(1.11.3 版本前,默认是 on),则工作进程将依次接受新的连接,就不会出现惊群现象。否则,如果有新连接进来,将通知所有 worker 进程有关新连接的信息,让所有的 worker 进程都来接收新连接,如果新连接的数量很少,则某些 worker 进程可能会浪费系统资源。

accept_mutex on;


返回限制

limit_conn 以及 limit_conn_zone – 限制 nginx 接受的客户端数量,例如从单个 ip 地址。设置它们可以帮助防止单个客户端打开过多的连接并消耗比其资源共享更多的资源。但是并非所有连接都被计数。仅当连接具有服务器正在处理的请求并且已经读取了整个请求标头时,才对连接进行计数。

# 配置示例

http {

    limit_conn_zone $binary_remote_addr zone=addr:10m;

    ...

    server {

        ...

        location /download/ {
            limit_conn addr 1;
        }
# 设置共享区域和给定键值的最大允许连接数。当超过此限制时,服务器将返回错误。
limit_conn_zone $binary_remote_addr zone=addr:10m;

server {
    location /download/ {
        limit_conn addr 1; # 一次每个 ip 地址只允许一个连接
    }
# 可能有几个limit_conn指令。例如,以下配置将限制每个客户端IP与服务器的连接数,并同时限制与虚拟服务器的连接总数
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;

server {
    ...
    limit_conn perip 10;
    limit_conn perserver 100;
    # 当且仅当 limit_conn 当前级别上没有指令时,这些指令才从上一级继承
}


limit_reqlimit_req_zone – 限制向客户端传输响应的速率。特别是从一个单一的IP地址的请求的处理速率。使用“漏斗”方法完成限制。它们还可以通过将请求速率限制为对人类用户合理的值,但对于试图通过请求淹没您的应用程序的程序(例如DDoS攻击中的机器人)太慢,可以提高安全性,尤其是对于登录页面而言。

# 配置示例
http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

    ...

    server {

        ...

        location /search/ {
            limit_req zone=one burst=5;
        }

设置共享内存区域和请求的最大突发大小。如果请求速率超过为区域配置的速率,则会延迟其处理,以便以定义的速率处理请求。过多的请求将被延迟,直到其数量超过最大突发大小为止,在这种情况下,该请求将因为错误而终止。

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

server {
    location /search/ {
        limit_req zone=one burst=5;
    }

上面这段配置的意思是平均每秒最多允许不超过1个请求,并且并发不超过5个请求。如果不需要等待延迟排队的请求,可以直接加上 nodelay 参数。

limit_req zone=one burst=5 nodelay;

可能有多个 limit_req 指令。例如,以下配置将限制来自单个IP地址的请求的处理速度,同时限制虚拟服务器的请求处理速度。

limit_req_zone $binary_remote_addr zone=perip:10m rate=1r/s;
limit_req_zone $server_name zone=perserver:10m rate=10r/s;

server {
    ...
    # 当且仅当 limit_req 当前级别上没有指令时,这些指令才从上一级继承 。
    limit_req zone=perip burst=5 nodelay;
    limit_req zone=perserver burst=10;
}


gzip 压缩

gzip 压缩使用的是 nginx 的 ngx_http_gzip_module 模块。开启 gzip 压缩后,nginx 会在返回内容前将内容压缩后返回,可以减少带宽和提高传输速度,给用户更好的体验。但是压缩文件也会消耗 cpu 资源,所以要合理使用。

http {
    gzip on; # 开启压缩
    gzip_min_length  1k; # 低于 1 K 不压缩
    gzip_buffers     4 16k; # 设置用于压缩响应的number和size的缓冲区
    gzip_http_version 1.1; # 设置压缩响应所需的最低 http 版本请求
    gzip_comp_level 2; # 压缩级别 1-9,越大压缩率越高,同时消耗cpu资源也越多,建议设置在4左右
    gzip_types     text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss; # 压缩文件类型
    gzip_vary on; # 是否添加 Vary: Accept-Encoding 响应头
    gzip_proxied   expired no-cache no-store private auth; # 根据请求和响应为代理请求启用或禁用响应的压缩
    gzip_disable   "MSIE [1-6]\."; # 配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
}

查看文件是否 gzip 压缩,直接在浏览器的返回 Response Headers 头中查看是否存在 content-encoding: gzip 参数。


expires 缓存

对于一些静态文件,我们可以利用 nginx 的 expires 模块来缓存到浏览器中,不必要每次访问到从服务器获取。

expires 30s; # 表示把数据缓存30秒
expires 30m; # 表示把数据缓存30分
expires 10h; # 表示把数据缓存10小时
expires 1d; # 表示把数据缓存1天

location ~* \.(gif|jpg|jpeg|png) {
    root  root/images;
    expires 3d;
}

用 chrome 浏览器抓下包,cache 那一列是 memory cache 就证明这次访问是从浏览器中取的缓存,如果想从服务器获取,直接强刷以下就可以了。


参考资料:

Tuning NGINX for Performance

结束语:感谢您对本网站文章的浏览,欢迎您的分享和转载,但转载请说明文章出处。
Top