Nginx优化

来自linux中国网wiki
Evan讨论 | 贡献2024年8月26日 (一) 02:53的版本 →‎配置优化
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索


nginx 配置和目录说明

yum安装nginx的默认目录详解

自定义的配置文件放在/etc/nginx/conf.d

ginx配置文件nginx.conf conf.d(一般都放这个目录下)

Nginx安装,目录结构与配置文件详解

Nginx详解(正向代理、反向代理、负载均衡原理)

nginx配置文件

user nginx nginx;                #定义Nginx运行的用户和用户组
worker_processes 1;            #nginx进程数,建议设置为等于CPU总核心数。
error_log /var/log/nginx/error.log info;      #全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
pid /var/run/nginx.pid;                #进程文件
worker_rlimit_nofile 35535;          #一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀,所以#建议与ulimit -n的值保持一致

events
{
use epoll;          #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,
                如果跑在FreeBS  #D上面,就用kqueue模型。

worker_connections 65535;        #单个进程最大连接数(最大连接数=连接数*进程数)
}



http                        #HTTP区块开始
{
include mime.types;                      #Nginx支持的媒体类型库文件
default_type application/octet-stream;       #默认媒体类型
#charset utf-8;                     #默认编码
server_names_hash_bucket_size 128;         #服务器名字的hash表大小
client_header_buffer_size 32k;               #上传文件大小限制
large_client_header_buffers 4 64k;             #设定请求缓
client_max_body_size 8m;                      #设定请求缓
sendfile on;       #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为o  #ff,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
autoindex on;                   #开启目录列表访问,合适下载服务器,默认关闭。
tcp_nopush on;               #防止网络阻塞
tcp_nodelay on;              #防止网络阻塞
keepalive_timeout 120;             #连接超时,单位是秒

#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;

#gzip模块设置
gzip on;                         #开启gzip压缩输出
gzip_min_length 1k;                 #最小压缩文件大小
gzip_buffers 4 16k;                #压缩缓冲区
gzip_http_version 1.0;               #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
gzip_comp_level 2;                   #压缩等级
gzip_types text/x-javascript text/css application/xml;    #压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
gzip_vary on;
#limit_zone crawler $binary_remote_addr 10m;   #开启限制IP连接数的时候需要使用



##
        # Gzip Settings from debian 默认的 折中办法
        ##

        gzip on;

         gzip_vary on;
         gzip_proxied any;
         gzip_comp_level 6;
         gzip_buffers 16 8k;
         gzip_http_version 1.1;
         gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

}

#虚拟主机的配置
server
{

listen 80;                         #监听端口

server_name localhost;                  #提供服务的域名主机名
location / {                    #第一个location区块开始
root html;                      #站点的根目录,相当于Nginx的安装目录
index index.html index.htm index.jsp;        #默认的首页文件,多个用空格分开
}                          #第一个location区块结果



#图片缓存时间设置
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 10d;
}


#JS和CSS缓存时间设置
location ~ .*\.(js|css)?$
{
expires 1h;
}


#日志格式设定
log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';

access_log /var/log/nginx/access_$(data+%F -d -1day).log access;    #定义本虚拟主机的访问日志



location / {                              #对 "/" 启用反向代理
proxy_pass http://127.0.0.1:88;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;        #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

#以下是一些反向代理的配置,可选
proxy_set_header Host $host;
client_max_body_size 10m;                 #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k;             #缓冲区代理缓冲用户端请求的最大字节数,
proxy_connect_timeout 90;            #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 90;                 #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 90;            #连接成功后,后端服务器响应时间(代理接收超时)
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;                #设定缓存文件夹大小,大于这个值,将从upstream服务器传

}

#设定查看Nginx状态的地址
location /NginxStatus {
stub_status on;
access_log on;
auth_basic "NginxStatus";
auth_basic_user_file conf/htpasswd;          #htpasswd文件的内容可以用apache提供的htpasswd工具来产生。

}

#本地动静分离反向代理配置
#所有jsp的页面均交由tomcat或resin处理
location ~ .(jsp|jspx|do)?$ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080;
}


#所有静态文件由nginx直接读取不经过tomcat或resin
location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
{ expires 15d; }
location ~ .*.(js|css)?$
{ expires 1h; }
}
}

内核参数优化

net.ipv4.tcp_max_tw_buckets = 5000  #表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为 180000,改为 5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。

net.ipv4.ip_local_port_range = 1024 65000  #表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000 
net.ipv4.tcp_tw_reuse = 1 #  开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭  
net.ipv4.tcp_tw_recycle = 1 # 开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭 注意 用clb 不能打开

net.ipv4.tcp_syncookies = 1 # 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.core.somaxconn = 262144 #每个监听端口允许的最大的监听队列长度,这个值应该适当增大

net.core.netdev_max_backlog = 16384 #有人是262144  #该参数决定了, 每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目, 不要设的过大

net.ipv4.tcp_max_orphans = 262144 #  系统所能处理不属于任何进程的TCP sockets最大数量。假如超过这个数量,那么不属于任何进程的连接会被立即reset,并同时显示警告信息。之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐千万不要依赖这个或是人为的降低这个限制,更应该增加这个值(如果增加了内存之后)。每个孤儿套接字最多能够吃掉你64K不可交换的内存。

系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。

net.ipv4.tcp_max_syn_backlog = 8192
表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数 进入SYN包的最大请求队列.默认1024.对重负载服务器,可调整到2048
记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128。

net.ipv4.tcp_synack_retries = 1
tcp_synack_retries 显示或设定 Linux 核心在回应 SYN 要求时会尝试多少次重新发送初始 SYN,ACK 封包后才决定放弃。这是所谓的三段交握 (threeway handshake) 的第二个步骤。即是说系统会尝试多少次去建立由远端启始的 TCP 连线。tcp_synack_retries 的值必须为正整数,并不能超过 255。因为每一次重新发送封包都会耗费约 30 至 40 秒去等待才决定尝试下一次重新发送或决定放弃。tcp_synack_retries 的缺省值为 5,即每一个连线要在约 180 秒 (3 分钟) 后才确定逾时.

net.ipv4.tcp_syn_retries = 1
对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右时间。(对于大负载而物理通信良好的网络而言,这个值偏高,可修改为2.这个值仅仅是针对对外的连接,对进来的连接,是由tcp_retries1 决定的)

net.ipv4.tcp_fin_timeout = 30
如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60秒。2.2 内核的通常值是180秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB服务器,也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能吃掉1.5K内存,但是它们的生存期长些。

net.ipv4.tcp_keepalive_time = 30 单位是秒

当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时 缺省是2小时,(1200)20分钟


Linux内核调试方法总结之sysrq

配置优化

note 如果是docker 选择alpine 轻量

1.    gzip压缩优化
2.    expires缓存有还
3.    网络IO事件模型优化 使用epoll的I/O模型
4.    隐藏软件名称和版本号
5.    防盗链优化
6.    禁止恶意域名解析
7.    禁止通过IP地址访问网站
8.    HTTP请求方法优化
9.    防DOS攻击单IP并发连接的控制,与连接速率控制
10.    严格设置web站点目录的权限
11.    将nginx进程以及站点运行于监牢模式
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


Events模块

events { 
worker_connections 2048; 
multi_accept on; 
use epoll; 


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


gzip on;

keepalive_timeout 60;

1、基本安全优化

1.1  隐藏版本信息

在http模块下加入:

server_tokens off;

删除欢迎主页

cd /usr/share/nginx/html
echo >index.html

1.2  隐藏nginx要修改源代码

要修改内容的路径:

第一路径:

1 nginx-1.6.3/src/core/nginx.h 第14,16行
2 #define NGINX_VERSION  "1.6.2" 修改为想要的版本号如2.4.3
3 #define NGINX_VER "nginx/" NGINX_VERSION 将nginx修改为想要修改的软件名称,如Apache。


第二路径

1 nginx-1.6.3/src/http/ngx_http_header_filter_module.c第49行
2 grep 'Server:nginx' ngx_http_header_filter_module.cstatic
3 sed -i 's#Server:nginx#Server:Apache#g' ngx_http_header_filter_module.c


第三路径

nginx-1.6.3/src/http/ngx_http_special_response.c第21,30行
"<hr><center>"NGINX_VER "(http://oldboy.blog.51cto.com)</center>" CRLF
"<hr><center>OWS</center>" CRLF
然后重新编译

1.3  更改nginx服务的默认用户

  --user=www --group=www

1.4  降权启动nginx

2、根据参数优化nginx服务性能

2.1  优化nginx进程个数的策略

在高并发、高访问量的web服务场景,需要事先启动好更多的nginx进程,以保证快速响应并处理大量并发用户的请求。

worker_processes  1;一般调整到与CPU的颗数相同

(1)查看LInux可查看CPU个数及总核数
grep processor /proc/cpuinfo|wc -l

(2)查看CPU总颗数
grep 'physical id' /proc/cpuinfo|sort|uniq|wc -l

(3)通过执行top命令,然后按数字1,即可显示所有的CPU核数

top  按1键就会显示第一个的信息

Cpu0  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0 

https://nginx.org/en/docs/ngx_core_module.html

2.2优化绑定不同的nginx进程到不同的CPU上

默认情况下,nginx的进程跑在某一个CPU或CPU的某一个核上,导致nginx进程使用硬件的资源不均,本节的优化是不同的nginx进程给不同的CPU处理,充分有效的利用有效的硬件资源

1.4核CPU,开户4个进程
worker_processes    4;
worker_cpu_affinity 0001 0010 0100 1000;


2.双核配置CPU,开启2个进程

worker_processes    2;
worker_cpu_affinity 01 10;


3. worker_processes 8;
nginx 进程数,建议按照cpu 数目来指定,一般为它的倍数 (如,2个四核的cpu计为8)。

 worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;

为每个进程分配cpu,上例中将8 个进程分配到8 个cpu,当然可以写多个,或者将一个进程分配到多个cpu。

4. 4核CPU,开启2个进程

worker_processes     2;
worker_cpu_affinity 0101 1010;


nginx worker_cpu_affinity使用方法

worker_cpu_affinity

https://www.cnblogs.com/pangbing/p/6537188.html

https://www.fujieace.com/nginx/worker.html

https://blog.csdn.net/u011957758/article/details/50959823

worker_rlimit_nofile

worker_rlimit_nofile 65535;

这个指令是指当一个nginx 进程打开的最多文件描述符数目,理论值应该是最多打开文
件数(ulimit -n)与nginx 进程数相除,但是nginx 分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。

现在在Linux 2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应应该填写65535。

这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。

查看linux系统文件描述符的方法:


#这个不太一样 注意 
[root@web001 ~]# sysctl -a | grep fs.file

fs.file-max = 789972

fs.file-nr = 510 0 789972


java-01 nginx]#  sysctl -a | grep fs.file
fs.file-max = 789880
fs.file-nr = 1504	0	789880
fs.xfs.filestream_centisecs = 3000
sysctl: reading key "net.ipv6.conf.all.stable_secret"
sysctl: reading key "net.ipv6.conf.br-c9b7840ce3c6.stable_secret"
sysctl: reading key "net.ipv6.conf.default.stable_secret"
sysctl: reading key "net.ipv6.conf.docker0.stable_secret"
sysctl: reading key "net.ipv6.conf.eth0.stable_secret"
sysctl: reading key "net.ipv6.conf.eth1.stable_secret"
sysctl: reading key "net.ipv6.conf.lo.stable_secret"
sysctl: reading key "net.ipv6.conf.veth87c2bc5.stable_secret"

worker_connections 65535

worker_connections 65535;

每个进程允许的最多连接数, 理论上每台nginx 服务器的最大连接数为worker_processes*worker_connections。

keepalive_timeout

keepalive_timeout 60;

keepalive 超时时间

一些暂时还没加上的nginx 配置优化

7.  client_header_buffer_size 4k;

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

分页大小可以用命令getconf PAGESIZE 取得。

[root@web001 ~]# getconf PAGESIZE 

4096

但也有client_header_buffer_size超过4k的情况,但是client_header_buffer_size该值必须设置为“系统分页大小”的整倍数。

8.  open_file_cache max=65535 inactive=60s;

这个将为打开文件指定缓存,默认是没有启用的,max 指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。

9.  open_file_cache_valid 80s;

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

10.  open_file_cache_min_uses 1;

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

2.3 nginx事件处理模型优化

nginx的连接处理机制在于不同的操作系统会采用不同的I/O模型,Linux下,nginx使用epoll的I/O多路复用模型,在freebsd使用kqueue的IO多路复用模型,在solaris使用/dev/pool方式的IO多路复用模型,在windows使用的icop等等。 
要根据系统类型不同选择不同的事务处理模型,选择有“use [ kqueue | rtsig |epool |dev/pool |select |pllo ];”我们使用的是Centos,因此将nginx的事件处理模型调整为epool模型。

events {
worker_connections  1024;
use epoll;

 multi_accept on;
}

2.8 配置nginx gzip压缩实现性能优化


http模块中加入gzip的配置

我常用的例子 

 gzip  on;  
 gzip_min_length 1k;
 gzip_comp_level 3; 
 gzip_proxied    expired ;
 gzip_types text/plain  application/javascript text/xml text/css; 

#老的不正确写法 
 #gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css; 


 gzip_disable "MSIE [1-6]\."; 
 gzip_vary on;

  gzip_buffers 4 16k;                #压缩缓冲区
  gzip_http_version 1.0;               #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)

#debina 10自带的写法
      gzip on;

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
#debina 10自带的写法



测试效果

 curl -I -H "Accept-Encoding: gzip, deflate" "mq.com"
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Thu, 22 Aug 2019 09:25:01 GMT
Content-Type: text/html
Connection: keep-alive
Vary: Accept-Encoding
etag: W/"2505434914"
last-modified: Tue, 20 Aug 2019 02:27:20 GMT
Content-Encoding: gzip #看到没 有gzip 




 curl -I -H "Accept-Encoding: gzip, deflate" "a.com"
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Wed, 21 Aug 2019 02:35:39 GMT
Content-Type: text/html
Content-Length: 8
Last-Modified: Mon, 19 Aug 2019 07:14:41 GMT
Connection: keep-alive
ETag: "5d5a4c61-8"
Accept-Ranges: bytes



下面是解说 

 gzip  on;   #开启gzip
 gzip_min_length 1k; #低于1kb的资源不压缩
 gzip_comp_level 3; #压缩级别【1-9】,越大压缩率越高,同时消耗cpu资源也越多,建议设置在4左右。
 gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;  #需要压缩哪些响应类型的资源,多个空格隔开。不建议压缩图片,下面会讲为什么。
 gzip_disable "MSIE [1-6]\.";  #配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
 gzip_vary on;  #是否添加“Vary: Accept-Encoding”响应头

 gzip_buffers 4 16k;                #压缩缓冲区
 gzip_http_version 1.0;               #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
#limit_zone crawler $binary_remote_addr 10m;   #开启限制IP连接数的时候需要使用


gzip_buffers

设置用于处理请求压缩的缓冲区数量和大小。比如32 4K表示按照内存页(one memory page)大小以4K为单位(即一个系统中内存页为4K),申请32倍的内存空间。建议此项不设置,使用默认值



官方eg 
gzip            on;
gzip_min_length 1000;
gzip_proxied    expired no-cache no-store private auth;
gzip_types      text/plain application/xml;


Note

在应用服务器前,公司还有一层Nginx的集群作为七层负责均衡,在这一层上,是没有开启gzip的。
如果我们使用了proxy_pass进行反向代理,那么nginx和后端的upstream server之间默认是用HTTP/1.0协议通信的。
如果我们的Cache Server也是nginx,而前端的nginx没有开启gzip。
同时,我们后端的nginx上没有设置gzip_http_version为1.0,那么Cache的url将不会进行gzip压缩
我相信,以后还有人会入坑,比如你用Apache ab做压测,如果不是设置gzip_http_version为1.0,你也压不出gzip的效果(同样的道理)。

Gzip proxied

Nginx开启Gzip详解

https://blog.csdn.net/huangbaokang/article/details/79931429

Nginx gzip的配置和校验

nginx开启gzip压缩功能遇到的坑

2.9 nginx expires功能

nginx如何启用ETag,提高访问速度

开启gzip时,可能与etag出现冲突,用浏览器多次请求此网站的静态元素,如果只返回200,不返回304,证明存在冲突,请去步骤4;没有冲突去步骤2

Nginx如何启用ETag,提高访问速度


未完 可查看下面


nginx的优化非常好的

Nginx配置性能优化


nginx优化 突破十万并发


other

grep 'open files' /proc/$( cat /var/run/nginx.pid )/limits   这个可以查看到nginx实际最大连接数

刚才看是1024 配置文件是65535 设置了下nginx.service文件 添加了LimitNOFILE=65535


see also

Nginx启动SSL功能,并进行功能优化


nginx常见问题处理


CentOS 6.3下Nginx性能调优

Nginx 配置详解

nginx优化 突破十万并发

Nginx高并发下的优化