Nginx 性能优化

1、调整 worker 进程数

nginx 有一个 master 进程和多个 work 进程。master 进程的主要目的是读取和评估配置,并维护 work 进程。work 进程对请求进行实际处理。在高并发、高访问的场景下,需要提前启动更多的 nginx 进程,以保证快速响应,处理大量并发用户的请求。

现在的服务器基本上都是多线程和多进程的,而 Nginx 默认不允许处理多个工作负载,因此你可以修改配置文件中worker_processes参数使其作为多线程 web 服务器来工作。

# 查看CPU核心数
grep processor /proc/cpuinfo | wc -l
2

如何在 Nginx 服务器上配置?

# 于是可设置工作进程为4并绑定到不同CPU
worker_processes  2;  # 如果设置未auto,就不需要手动绑定,它会自动绑定
# 如果你的服务器是2核
worker_cpu_affinity 0101 1010;

# 如果你的服务器是4核
# worker_cpu_affinity 0001 0010 0100 1000;
# 如果你的服务器是8核
# worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;

2、调整 worker 连接数

work 连接数work 进程数息息相关,可通过 worker_connections 参数设置 work 连接数。worker_connections 参数用于设置 Nginx 单个 work 进程(worker_processes)允许的最大客户端连接数。

而 Nginx 默认的 1024 在生产环境来说是比较小的,因此需要调整该参数。该配置参数位于 events 事件中,Linux 中 nginx 采用 epoll 的 I/O 复用模型,FreeBSD 中使用 kqueue 的 I/O 复用模型,Solaris 中使用 /dev/poll 的 I/O 复用模型,Windows中使用 ICOP 等。

因此,我们需要针对不同的系统类型来选择不同的事件处理模型。我用的是 CentOS 7,所以把 nginx 的事件处理模型调整为 epoll 模型。

如何在 Nginx 服务器上配置?

events {
    use epoll;
    worker_connections  20240;
    multi_accept on;
}

还有一个参数也是需要注意的,就是 multi_accept on,该参数告诉 nginx 收到一个新连接通知后接受尽可能多的连接,默认是on,且为串行处理连接数。当为 off 时为并行处理连接数,即多个 work 进程同时处理连接。因此,当你的客户端连接数较少时,参数值置为 on,相反在连接数较多、服务器吞吐量较大时,参数值置 off,可提高 Nginx 性能。

当然,这个 work 连接数也不是说可无限设置大,它和系统自身内存最大文件打开数有关。一个连接分别对应一个 read_event 和一个 write_event 事件。一个连接本身占用 232 字节左右,两个事件总占 96 字节左右,于是一个连接(连接 + read_event + write_event)总共就占 328 字节。

因此,上面的 20240 的连接数就会占用 20240*328/1024/1024 = 6M 大小内存。

在来看看 worker 进程最大打开文件数,该值其实在我们设置系统最大打开文件数的时候已经指定(*/指定用户),如下所示:

cat /etc/security/limits.conf

...
root soft nofile 65535
root hard nofile 65535
* soft nofile 65535
* hard nofile 65535
# End of file

因此,只需要设置 worker_rlimit_nofile 值为以上 65535 值即可。

# 配置Nginx worker进程最大打开文件数
worker_rlimit_nofile 65535;

3、调整 work 进程最大打开文件数

接下来调整配置 nginx 的 worker 进程的最大打开文件数,控制连接数的参数是 worker_rlimit_nofile,该值与 nginx 所在操作系统的最大打开文件数相关,也就是你 nginx 的 work 进程最大打开文件数必须小于或等于自身操作系统的最大打开文件数,要不然设置了也是没意义的。

# 先查看系统自身最大打开文件数
ulimit -n
65536

如何在 Nginx 服务器上配置?

# 控制在系统最大打开文件数内即可
worker_rlimit_nofile 65536;

需要注意:

4、开启高效文件传输模式

sendfile on|off 参数用于启用高效文件传输模式,默认是 off 的,作用域:http、server、location。该参数通常结合 tcp_nopush on|off 参数和 tcp_nodelay on|off 来防止网络和磁盘 I/O 阻塞,提升 nginx 效率。当开启 sendfile 后 tcp_nopush on|off 参数和 tcp_nodelay on|off 只能二选一,而且开启 sendfile 后默认启用的是 tcp_nopush on

  • tcp_nopush on|off:该参数会启用 tcp_cork 方法,仅当 sendfile 开启后生效,其功能是:当应用程序收到数据包时不会马上传送出去,而是等到数据包最大时,才一次性的传输出去。这样解决了网络堵塞问题。
  • tcp_nodelay on|off:该参数会启用 tcp_nodelay 方法,其功能是:当应用程序收到数据包时会尽量发送小数据块,而不是等一定数据量满了之后才发送。这样解决了磁盘I/O问题。

如何选择?下面注释写得比较清楚

如何在 Nginx 服务器上配置?

sendfile on;
# 解决网络拥塞问题
tcp_nopush on;
# 解决磁盘I/O问题
# tcp_nodelay on;

5、限制文件上传大小

限制文件上传大小 指的是 限制 HTTP 请求正文大小,通过 client_ max_ body_ Size 参数设置。如果上传文件的大小超过此设置,则会响应 413 Request Entity Too Large 错误代码。如果服务器涉及上传文件的业务,就可以通过该参数来限制。

如何在 Nginx 服务器上配置?

client_max_body_Size 10m;

nginx 对上传文件大小默认为 1m 大小,如果很大,还要适当调整上传超时时间。

  • client_header_timeout:读取请求头的超时时间,默认60秒。若超过所设定的大小,返回 408 错误。
  • client_body_timeout:读取请求实体的超时时间,默认60秒。若超过所设定的大小,返回 413 错误。

作为代理时的超时时间:

  • proxy_connect_timeout:HTTP 请求无法立即被容器(tomcat, netty 等)处理,被放在 nginx 的待处理池中等待被处理超时时间。默认为 60s,官方推荐最长不要超过 75s。
  • proxy_read_timeout:HTTP 请求被容器(tomcat, netty 等)处理完后,nginx 等待处理结果的时长,默认60秒。
  • proxy_send_timeout:HTTP 请求被容器(tomcat, netty 等)处理完后,把数据传返回给 nginx 的时长,默认60秒。

最终配置参考:

client_max_body_Size 10m;

# 其实以下参数你不配置,它都是默认生效的
client_header_timeout 60;
client_body_timeout 60;
proxy_connect_timeout 60;
proxy_read_timeout 60;
proxy_send_timeout 60;

6、开启 gzip 压缩

gzip 压缩模块提供了压缩文件内容的功能,在用户请求的内容发送到用户客户端之前,nginx 服务器会根据一些具体的策略执行压缩策略,从而节省网站的出口带宽,加快数据传输效率,提升用户体验。

最好是在有大文件时启用它,因为它本身也会消耗CPU资源。

gzip  on;
gzip_min_length  1k;
gzip_buffers     4 16k;
gzip_http_version 1.1;
gzip_comp_level 9;
gzip_types text/plain text/javascript application/javascript text/css application/xml application/json;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;

7、本地缓存静态资源

每个网站都有页面、图像和其他内容,这些内容在访问者在网站上的会话期间基本保持不变。现代网页上几乎 30% 的数据是静态的,应该缓存这些内容以提高 Nginx 的性能。

优点:

  • 静态资源加载快:因为不经过 Nginx 连接请求;
  • 降低了 Nginx 的连接请求压力:可降低 Nginx 服务器负载。

如何在 Nginx 服务器上配置?

location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 365d;
}

# 该语句将会在客户端(浏览器)请求后,将这些静态资源缓存于本地(浏览器),并且设置有效期365天

8、调整缓冲区大小

  • Client_header_buffer_size:限制客户端(浏览器)请求头大小,一般设置为 1k 左右。如果(请求行 + 请求头)的大小如果没超过1k,则放行请求。如果(请求行 + 请求头)的大小如果超过1k,则以large_client_header_buffers配置为准决定是否放行。

  • large_client_header_buffers:Client_header_buffer_size 的最大值。

    # 例如:
    large_client_header_buffers 2 1k
    
    # 请求行不能超过1k,否则返回414错误代码
    # 请求头不能超过1k,否则返回400错误代码
    # 请求行+请求头不能超过2k(2*1k),否则报错
    
  • Client_body_buffer_size:客户端(浏览器)在 web 网站上发布请求的缓冲区大小,一般设置 128k 左右。

  • Client_max_body_size:客户端(浏览器)在 web 网站上发布请求的最大主体大小,比如设置为 10m,当超过该值将向客户端返回 Request Entity Too Large 错误。

client_header_buffer_size 1k;
large_client_header_buffers 2 1k;  # 这里是2个1k的大小(即最大为2*1K=2K)
client_body_buffer_size 128k;
client_max_body_size 10m;

9、尽可能少使用 if 检查 server_name 语句

你想想,每一个请求连接进来都要进行一次 if 判断,这势必会增加 web 服务器开销,尤其是在十万/百万并发场景下。因此,你也可以在 if 语句层面来优化。

例如:server_name 指定 hello.com 和 www.hello.com 两个域名,当 Nginx 收到请求时,无论请求的是哪个子域,如果始终对 if 指令进行评估,那效率都是很低的。

  • 低效率配置

    server {
      server_name     hello.com www.hello.com;
      if ($host = www.hello.com) {
        return   301 https://hello.com$request_uri;
      }
    }
    
  • 高效率配置

    server {
        server_name      www.hello.com;
        return           301 $scheme://hello.com$request_uri;
        ## If you force your web traffic to use HTTPS:
        # return 301 https://domain.com$request_uri;
        ...
    }
    

10、避免过多正则表达

  • 低效率配置

    ...
    rewrite ^/(.*)$ https://example.com/$1 permanent;
    # 或
    rewrite ^ https://example.com$request_uri? permanent;
    ...
    
  • 高效率配置

    ...
    return 301 https://example.com$request_uri;
    # $request_uri就是完整url中刨去最前面$host剩下的部分
    # 比如:http://www.baidu.com/test
    # 那么$request_uri的值就是/test
    # 如果只有:http://www.baidu.com,那么$request_uri的值就是/
    ...
    

11、return 代替 rewrite 实现重定向

  • 低效率配置

    server {
      ...
      if ($host = api.domain.com) {
        rewrite     ^/(.*)$ http://example.com/$1 permanent;
      }
      ...
    }
    
  • 高效率配置

    server {
      ...
      if ($host = api.domain.com) {
        return      403;
        ## or other examples:
        ##   return    301 https://domain.com$request_uri;
        ##   return    301 $scheme://$host$request_uri;
      }
      ...
    }
    

12、使用 try_files 指令确认文件是否存在

  • 低效率配置

      ...
      root /var/www/example.com;
      location /images {
        if (-f $request_filename) {
          expires 30d;
          break;
        }
      ...
      }
    
  • 高效率配置

      ...
      root /var/www/example.com;
      location /images {
        try_files $uri $uri/ =404;
      ...
      }
    
    # 比如,我请求 http://www.hello.com/images  那$uri的值就是/images
    # $uri:Nginx 首先判断images是否是个文件且存不存在,如果是且存在则返回,否则继续$uri/判断
    # $uri/:Nginx 再次判断images/是否是个目录且存不存在,如果是且存在则返回,否则将返回404错误代码
    

13、设置 keepalive_timeout

一般地,在我们的 web 网站中,为了避免同一个客户长时间占用连接,造成资源浪费,可设置相应的超时时间,实现对连接访问时间的控制。

keepalive_timeout 65 180

# 第一个参数值65:表示客户发送请求头的超时时间,服务器会在这个时间之后关闭连接
# 第二个参数值180:表示请求体读超时时间,客户端(浏览器)会在这个时间后关闭连接

企业生产环境中,我们一般设置为该值就可以了(当然也需要根据实际情况来调整)。

14、日志文件轮转

随着业务量的增加,web 服务的日志访问量也越来越大,久而久之将会耗尽系统磁盘空间。因此,日志轮转就显得非常重要了,有关日志轮转的相关知识的可查看我之前的博文《Linux系统之计划任务及日志轮转》

# 编辑nginx轮转文件
cat /etc/logrotate.d/nginx

/data/nginx/logs/access.log {
    missingok   # 丢失不提醒
    notifempty  # 空文件不轮转
    maxsize 4G  # 只要到了4G日志大小就轮转
    rotate 4    # 保留文件数
    daily       # 每天轮转一次
    create 0600 root root
}

日志轮转可配合计划任务来实现自动轮转!!

<点击跳转至开头>

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云计算-Security

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值