优化

基础优化

以普通用户身份运行 Nginx

  • 启动Nginx工作进程的用户和组,(指定的是workr进程的身份,master进程始终是以root身份运行的,因为80端口只有特权用户才可以监听)
user nginx nginx;

worker 进程相关优化

开启和 CPU 核心数相同的 worker 进程

  • 启动nginx worker进程的数量,一般和cpu核心数相同,也可以定义为auto,表示根据CPU核心数量自动匹配
worker_processes  < number | auto >;

CPU 核心与 worker 进程进行亲缘性绑定

  • 将worker进程绑定在某一颗cpu上,这样可以减少进程与不同cpu的反复切换,从而提升性能,0001 0010 0100 1000表示 四颗cpu;0号-3号cpu
worker_cpu_affinity 0001 0010 0100 1000;

worker 的优先级

  • 可选
  • -20优先级最高,19优先级最低,默认为0

所有 worker 进程能打开的文件数量

worker_rlimit_nofile 65536;

每个 worker 进程的最大连接数

events {
    worker_connections  10240;
}

每个 worker 可以同时接受多个新的网络连接

events {
    multi_accept on; # on时Nginx服务器的每个工作进程可以同时接受多个新的网络连接,此指令默认值为off,即默认为一个工作进程只能接受一个网络连接,建议优化,建议此值设为on

}                             

事件驱动模型优化

使用 epoll 的事件驱动模型(默认值)

events {
    use epoll;
}

http 响应首部优化

隐藏 nginx 版本号

http {
    server_tokens off;
}

其他优化

  • 开启压缩
  • 防盗链

高并发优化

  • nginx要高并发需要硬件和软件多方面的支持才能实现高并发
  • 其中主要包括内存、nginx配置、内核参数优化、limit限制优化
  • 下面是配置范例

内存支持

  • nginx默认为 epoll I/O模型
  • 最大并发链接数受内存限制,即内存越大,并发连接数则越高
#查看内存支持的最大并发链接数:
[root@aliyun ~]# free -h
              total        used        free      shared  buff/cache   available
Mem:          1.7Gi       288Mi       536Mi       4.0Mi       912Mi       1.3Gi
Swap:            0B          0B          0B
[root@aliyun ~]# cat /proc/sys/fs/file-max 
173515 #最大并发连接数

nginx配置优化

1.未做配置前测试

#测试客户端
[root@test ~]#ulimit -n 102400
[root@test ~]#while true;do ab -c 5000 -n 10000 http://10.0.0.8/;sleep 1;done
Benchmarking 10.0.0.8 (be patient)
socket: Too many open files (24) #提示打开文件太多

#服务端
[root@centos8 ~]#tail -f /apps/nginx/logs/error.log
2021/08/30 17:41:36 [crit] 1106#0: accept4() failed (24: Too many open files) #同样显示打开文件过多

2.修改服务端配置

#修改nginx配置文件
[root@centos8 ~]#vim /apps/nginx/conf/nginx.conf
worker_rlimit_nofile 65536;

events {
    worker_connections  10240;
}

#永久修改ulimit值:添加如下两行,重启或ulimit -n 1000000生效
[root@centos8 ~]#vim /etc/security/limits.conf
*                soft    nofile         1000000
*                soft    nofile         1000000

#重启服务
[root@centos8 ~]#systemctl restart nginx.service

3.测试

#测试段OK
[root@test ~]#while true;do ab -c 5000 -n 10000 http://10.0.0.8/;sleep 1;done
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 10.0.0.8 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests

#服务端无错误日志
[root@centos8 ~]#tail -f /apps/nginx/logs/error.log

内核参数优化

...

limit配置优化

#永久修改ulimit值:添加如下两行,重启或ulimit -n 1000000生效
[root@centos8 ~]#vim /etc/security/limits.conf
*                soft    nofile         1000000
*                soft    nofile         1000000

长连接优化

  • 使用keepalive可以复用tcp连接从而提升性能
  • 长时间的TCP连接会导致系统资源被长时间占用,浪费资源,所以在实际使用的时候,还需要为keepalive设置合理的 timeout
  • 核心模块提供此功能

keepalive_timeout

  • 保持连接超时时长
  • Syntax:
    • keepalive_timeout timeout [header_timeout];
      • 0 表示禁止长连接,默认为75s
  • Default:
    • keepalive_timeout 75s;
  • Context:
    • http, server, location

keepalive_requests

  • keepalive的最大请求数

  • Syntax:

    • keepalive_requests number;
  • Default:

    • keepalive_requests 1000;
  • Context:

    • http, server, location

范例:

keepalive_requests 3; # 单次长连接请求数超过3次则断开长连接

keepalive_timeout 65 60; #设置回话保持时间(65为实际保持的时间,60表示显示的时间),如不写60则不会在响应报文头中显示时间

#可以用telnet测试超时时间
telnet www.xiangzheng.com 80

#未进行长连接配置时的响应报文头显示
[root@clicent ~]#curl -I  www.xiangzheng.com/index
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Thu, 13 Jan 2022 13:13:13 GMT
Content-Type: text/html
Content-Length: 29
Last-Modified: Thu, 13 Jan 2022 04:11:43 GMT
Connection: keep-alive #默认值75s后自动断开长连接
ETag: "61dfa67f-1d"
Accept-Ranges: bytes


#进行长连接配置后的响应报文头显示
[root@clicent ~]#curl -I  www.xiangzheng.com/index
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Thu, 13 Jan 2022 13:22:19 GMT
Content-Type: text/html
Content-Length: 29
Last-Modified: Thu, 13 Jan 2022 04:11:43 GMT
Connection: keep-alive
Keep-Alive: timeout=60 #不写60则不会显示
ETag: "61dfa67f-1d"
Accept-Ranges: bytes

上传文件大小限制

  • 设置客户端请求正文的最大允许大小。如果请求中的大小超过配置的值,则会向客户端返回 413(请求实体太大)错误。设置size为 0 将禁用对客户端请求正文大小的检查。
  • Syntax:client_max_body_size size;
  • Default:client_max_body_size 1m;
  • Context:http, server, location

优化总结

  • 性能优化:

  • 指定worker进程的数量,一般与cpu核心个数相同,或者设置为auto 即自动匹配

  • worker进程和cpu某一核心进行绑定(防止worker进程在cpu核心上频繁切换而影响性能)

  • 调大每个nginx最大的打开的文件数量 和 每个work进程能接受的最大连接数(还需要同时修改内核参数和limit限制文件)

  • 设置每个work进程可以同时接受多个网络连接

  • accept_mutex on,表示同一时刻一个请求轮流由work进程处理,防止因接受一个请求而导致所有worker进程被唤醒,从而避免产生惊群效应

  • multi_accept on,让Nginx服务器的每个工作进程可以同时接受多个新的网络连接

  • 开启gzip压缩

  • 缓存:

    • SSL缓存
    • xx 缓存??
    • xx 缓存??
  • 安全优化:

  • 隐藏nginx版本号

  • 以普通用户的身份运行work进程

  • 严格限制站点目录的权限

  • 禁止通过IP地址访问网站

  • 限制上传到资源目录的程序被访问,防止木马入侵系统破坏文件

  • 反向代理相关优化:

  • 开启缓存(告诉客户端是否命中缓存等)

  • 添加头部报文信息

  • 客户端IP透传(在后端server日志中显示真实的客户端公网IP,而非代理服务器的IP)

  • 防盗链优化

  • 其他优化:

  • 自定义错误页面进行友好展示

  • 有ELK的话将日志输出格式改为json

  • 在主配置文件中添加 include 制定子配置文件 方便管理

  • 1.gzip压缩优化
    2.expires缓存优化
    3.网络IO事件模型优化
    4.隐藏软件名称和版本号
    5.防盗链优化
    6.禁止恶意域名解析
    7.禁止通过IP地址访问网站。
    8.HTTP请求方法优化。
    9.防DOS攻击单IP并发连接的控制,与连接速率控制。
    10.严格设置Web站点目录的权限。
    11.将Nginx进程以及站点运行于监牢模式(nginx服务降权启动(不能使用80端口,使用其他端口,例如8080)、站点目录设置普通用户)12.通过robot协议以及HTTP_USER_AGENT防爬虫优化
    13.配置错误页面根据错误码指定网页反馈给用户
    14.Nginx日志相关优化
    访问日志切割轮询、不记录指定元素日志、最小化日志目录权限。
    15.限制上传到资源目录的程序被访问,防止木马入侵系统破坏文件。
    16.FastCGI参数buffer和cache以及超时等的优化。
    17.php.ini和php-fpm.conf配置文件的优化。
    18.有关Web服务的linux内核方面深度优化(网络连接、IO、内存等)。
    19.Nginx加密传输优化(SSL)。
    20.Web服务器磁盘挂载及网络文件系统优化。
    21.使用Nginx cache。
    22.nginx WAF(nginx+lua) 安全。

其他优化

Nginx 访问日志个输出格josn

缓存相关配置

proxy_cache

  • proxy_cache 是Nginx的反向代理缓存模块,它可以缓存反向代理服务器的响应内容,提高网站的访问速度,减少后端服务器的压力。

  • 开启 proxy_cache 缓存后,可以将一些频繁往后端服务器读取的数据缓存下来,从而提升效率

  • proxy_cache 缓存功能默认处于关闭状态

  • 注意事项:

    • 代码升级时一定要先删除缓存,否则只能看到指定时间内的缓存内容

      • 代码升级时一定要先删除缓存,否则只能看到指定时间内的缓存内容: 在使用proxy_cache模块时,需要注意在进行代码升级或者更新时,先清空缓存,否则会导致客户端只能看到之前缓存的内容而无法获取到最新的内容。因此,在进行代码更新时,一定要记得先清空缓存,可以通过手动删除缓存文件或者使用命令proxy_cache_bypass来实现。
    • 动态页面慎用缓存

      • proxy_cache模块适用于静态内容较多的网站,如果将动态页面进行缓存,可能会导致缓存的内容过时或者不一致,从而影响网站的性能和用户体验。因此,在使用proxy_cache模块时,需要根据具体的应用场景来选择需要缓存的内容,避免对动态内容进行缓存。
    • 除了以上两点,还有其他需要注意的地方,例如缓存时间的设置、缓存大小的限制等等,都需要根据实际情况进行配置和调整,以达到最优的缓存效果。

proxy_cache 相关参数说明

proxy_cache

  • 指明调用的缓存,或关闭缓存机制 以及 定义用于缓存的共享内存区域

  • 同一个共享内存区域可以在多个地方使用

Syntax:	proxy_cache zone | off; # zone表示缓存的名称,需要proxy_cache_path实现定义
Default:	proxy_cache off;
Context:	http, server, location

proxy_cache_key

  • 定义将哪些关键key缓存
Syntax:	proxy_cache_key string;
Default:	proxy_cache_key $scheme$proxy_host$request_uri;
Context:	http, server, location

proxy_cache_valid

  • 为不同的响应代码的响应内容设置缓存时间
Syntax:	proxy_cache_valid [code ...] time;
Default:	
Context:	http, server, location
范例
proxy_cache_valid 200 302 10m; # 为200 302响应码的内容缓存10分钟

proxy_cache_valid 404 1m; # 为404响应码的内容缓存1分钟

proxy_cache_valid 5m; # 只有 200、301 和 302 响应被缓存。

proxy_cache_valid any 1m; # 除设置的指定状态码外,其他的状态码缓存有效时间

proxy_cache_path

  • 设置缓存路径和其他参数
Syntax:	proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [min_free=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
Default:	
Context:	http
范例
...
http {
...
    proxy_cache_path /var/cache/nginx/proxy_cache # 定义缓存保存路径,proxy-cache会自动创建
    levels=1:2:2 # 定义缓存目录结构层次,1:2:2可以生成2^4x2^8^x2^8=2^20=1048567个目录
    keys_zone=proxycache:20m # 指定内存中缓存大小,主要用于存放key和metadata(如:使用次数)
    inactive=120s # 缓存有效时间
    max_size=1g; # 最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值
...    
}
...

proxy_cache_use_stale

  • 在被代理的后端服务器出现哪种情况下,可以直接使用过期的缓存响应客户端
Syntax:	proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | off ...;
Default:	proxy_cache_use_stale off;
Context:	http, server, location
范例
# 当后端服务器返回503或504响应码时直接将proxy中的缓存发送给server
proxy_cache_use_stale error http_503 http_504;

proxy_cache_methods

  • 指定哪些客户端请求方法将被缓存
Syntax:	proxy_cache_methods GET | HEAD | POST ...;
Default:	proxy_cache_methods GET HEAD;
Context:	http, server, location

proxy_cache 范例

开启缓存前测试

[root@clicent ~]# ab -n200 -c20 http://www.xiangzheng.com/web/test_file.txt
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.xiangzheng.com (be patient)
Completed 100 requests
Completed 200 requests
Finished 200 requests


Server Software:        nginx/1.18.0
Server Hostname:        www.xiangzheng.com
Server Port:            80

Document Path:          /web/test_file.txt
Document Length:        1183392 bytes

Concurrency Level:      20
Time taken for tests:   14.016 seconds
Complete requests:      200
Failed requests:        0
Write errors:           0
Total transferred:      236726600 bytes
HTML transferred:       236678400 bytes
Requests per second:    14.27 [#/sec] (mean)
Time per request:       1401.635 [ms] (mean)
Time per request:       70.082 [ms] (mean, across all concurrent requests)
Transfer rate:          16493.47 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   17  59.1      3     564
Processing:    54 1339 1535.8    523    6871
Waiting:        2  235 444.3    101    4032
Total:         54 1357 1550.4    524    7059

Percentage of the requests served within a certain time (ms)
  50%    524
  66%    990
  75%   1772
  80%   2327
  90%   4214
  95%   4273
  98%   4941
  99%   6951
 100%   7059 (longest request)

定义缓存

  • 只能在http语句块中定义缓存
[root@nginx-proxy ~]# vim /apps/nginx/conf/nginx.conf
...
http {
...    
    #cache setting
    proxy_cache_path /apps/nginx/proxy_cache
                    levels=2:2:2
                    keys_zone=nginx_proxy_cache:128m
                    inactive=180s
                    max_size=5g;
...
}
...


#说明
proxy_cache_path /apps/nginx/proxy_cache #定义缓存存放路径,proxy_cache文件会自动生成
levels=2:2:2 #定义缓存目录结构层次
keys_zone=nginx_proxy_cache:128m #指定缓存名称,内存中的缓存大小
inactive=180s #缓存有效时间
max_size=5g #磁盘中最大占用的空间

调用缓存

  • 一般定义在server,location语句块中
[root@nginx-proxy ~]# vim /apps/nginx/conf.d/pc.conf 
server {
    listen 80;
    server_name www.xiangzheng.com;
    location  /web {
        index index.html;
        proxy_pass http://10.0.0.18:80;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_cache nginx_proxy_cache; #指定调用的缓存
        proxy_cache_key $request_uri; #至缓存请求的uri
        proxy_cache_valid 200 302 301 10m; #200 302 301状态码缓存10分组
        proxy_cache_valid any 5m; #其他的缓存5分钟
    }
}

开启缓存后测试

[root@clicent ~]#ab -n200 -c20 http://www.xiangzheng.com/web/test_file.txt
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.xiangzheng.com (be patient)
Completed 100 requests
Completed 200 requests
Finished 200 requests


Server Software:        nginx/1.18.0
Server Hostname:        www.xiangzheng.com
Server Port:            80

Document Path:          /web/test_file.txt
Document Length:        1183392 bytes

Concurrency Level:      20
Time taken for tests:   1.490 seconds
Complete requests:      200
Failed requests:        0
Write errors:           0
Total transferred:      236726600 bytes
HTML transferred:       236678400 bytes
Requests per second:    134.21 [#/sec] (mean) #性能明显提升将近五倍
Time per request:       149.022 [ms] (mean)
Time per request:       7.451 [ms] (mean, across all concurrent requests)
Transfer rate:          155130.02 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1    2   0.9      2       7
Processing:    87  145  13.1    147     168
Waiting:        1    8   6.1      5      35
Total:         89  147  13.1    149     169

Percentage of the requests served within a certain time (ms)
  50%    149
  66%    152
  75%    155
  80%    157
  90%    160
  95%    164
  98%    168
  99%    168
 100%    169 (longest request)

代理端产生的缓存信息

  • 代码升级时一定要先删除缓存,否则只能看到指定时间内的缓存内容
#生成的文件
[root@nginx-proxy ~]# tree /apps/nginx/proxy_cache
/apps/nginx/proxy_cache
└── b0
    └── 35
        └── 7e
            └── e382ae236a505a58fe6780c98a7e35b0
            
#会在头部生成响应头部信息      
[root@nginx-proxy ~]# head /apps/nginx/proxy_cache/b0/35/7e/e382ae236a505a58fe6780c98a7e35b0 
 
䠬䟹	䟑R´󿿩Z"61e5046c-120ea0"
KEY: /web/test_file.txt
HTTP/1.1 200 OK
Server: nginx/1.14.1
Date: Mon, 17 Jan 2022 06:14:17 GMT
Content-Type: text/plain
Content-Length: 1183392
Last-Modified: Mon, 17 Jan 2022 05:53:48 GMT
Connection: close
ETag: "61e5046c-120ea0"

nginx缓存相关的配置参数如下:

  • proxy_cache_path:设置代理服务器缓存的存储路径和缓存区块大小,例如:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m inactive=60m;
  • proxy_cache:开启代理服务器缓存,例如:
proxy_cache my_cache;
  • proxy_cache_bypass:设置哪些请求不会被缓存,例如:
proxy_cache_bypass $http_pragma;
proxy_cache_bypass $http_authorization;
  • proxy_cache_valid:设置缓存的有效时间,例如:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404      1m;
  • proxy_cache_key:设置缓存的键,例如:
proxy_cache_key "$scheme$request_method$host$request_uri";
  • proxy_cache_lock:开启缓存锁,用于防止缓存过期时多个客户端同时请求源服务器,例如:
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;

这些配置参数可用于控制代理服务器缓存的行为,提高网站的性能和响应速度。

open_file_cache

open_file_cache模块可以缓存文件的元数据,包括文件名、访问时间、修改时间等信息,从而加速文件的访问速度。该模块可以减少磁盘I/O操作,提高网站的性能。

open_file_cache 是 nginx 中的一个指令,用于设置打开文件缓存,以减少文件 I/O 操作的次数,从而提高性能。具体来说,它会缓存已经打开的文件句柄,避免重复的文件打开和关闭操作,从而节省系统资源。

open_file_cache 指令支持以下参数:

  • open_file_cache max=X inactive=Ys;:设置打开文件缓存的大小和缓存项的过期时间。其中,X 表示缓存项的数量,Y 表示缓存项的过期时间。
  • open_file_cache_valid Xs;:设置缓存项的有效期,即缓存多久需要重新读取文件句柄。
  • open_file_cache_min_uses N;:设置文件句柄的最小使用次数。如果一个文件的句柄使用次数小于该值,就不会被缓存。
  • open_file_cache_errors on|off;:设置是否缓存文件打开时的错误信息。
  • open_file_cache_events on|off;:设置是否监听文件系统事件,并自动更新缓存。

例如,以下是一个 open_file_cache 的配置示例:

codeopen_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
open_file_cache_events on;

这个示例中,打开文件缓存最多可以缓存 1000 个文件句柄,每个缓存项的过期时间为 20 秒。缓存项的有效期为 30 秒,最小使用次数为 2。同时,还开启了缓存文件打开时的错误信息和监听文件系统事件。

open_file_cache 指令也与缓存相关。它缓存已经打开的文件描述符,以便nginx在需要访问这些文件时,无需重新打开文件,从而提高I/O效率。

与其他缓存指令类似,open_file_cache 指令允许nginx缓存磁盘上的文件句柄,以避免频繁的文件I/O操作。通过将打开的文件缓存起来,nginx可以减少打开和关闭文件的次数,从而降低对文件系统的访问负载,并提高I/O效率。因此,open_file_cache 指令也是与缓存相关的一个重要指令。

fastcgi_cache

fastcgi_cache模块可以缓存FastCGI的响应结果,从而加快动态请求的处理速度。该模块可以减少后端服务器的压力,提高网站的并发能力。

  1. fastcgi_cache_path:设置 FastCGI 缓存路径和缓存区块大小。
  2. fastcgi_cache:开启 FastCGI 缓存。
  3. fastcgi_cache_bypass:设置不缓存的条件,与 proxy_cache_bypass 类似。
  4. fastcgi_cache_valid:设置 FastCGI 缓存的有效时间。
  5. fastcgi_cache_key:设置 FastCGI 缓存的键,与 proxy_cache_key 类似。

uwsgi_cache

uwsgi_cache模块可以缓存uWSGI的响应结果,与fastcgi_cache类似,可以加速动态请求的处理速度。该模块可以提高网站的性能和并发能力。

  1. uwsgi_cache_path:设置 uWSGI 缓存路径和缓存区块大小。
  2. uwsgi_cache:开启 uWSGI 缓存。
  3. uwsgi_cache_bypass:设置不缓存的条件,与 proxy_cache_bypass 类似。
  4. uwsgi_cache_valid:设置 uWSGI 缓存的有效时间。
  5. uwsgi_cache_key:设置 uWSGI 缓存的键,与 proxy_cache_key 类似。