nginx有哪些常规调优手段详解

前言

大部分web应用都使用了nginx做负载均衡服务器,下面总结了nginx.conf中一些可以微调的配置。需要注意一点,这不是一个全面的微调指南。这是一个简单的预览——那些可以通过微调来提高性能设置的概述。你的情况可能不同。

nginx配置说明

nginx.conf中主要分高层配置、Events模块、HTTP 模块三个模块。下面依次介绍个模块可以微调的配置。

高层配置

user admin; #定义Nginx运行的用户
error_log ar/loginx/error.log info; #全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
access_log off; #定义本虚拟主机的访问日志
pid ar/runinx.pid; #进程文件
worker_processes auto; #nginx进程数
worker_rlimit_nofile 65535; #一个nginx进程打开的最多文件描述符数目

可以微调的配置:

  • worker_processes:建议设置为等于CPU总核心数。
  • worker_rlimit_nofile:理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀,所以建议与ulimit -n的值保持一致。

Events模块

events {
use epoll; #设置用于复用客户端线程的轮询方法,[ kqueue | rtsig | epoll | /dev/poll | select | poll ]
worker_connections 65535; #单个进程最大连接数(最大连接数=连接数*进程数)
multi_accept on; #开启后告诉nginx收到一个新连接通知后接受尽可能多的连接
}

可以微调的配置:

  • use:如果你使用Linux 2.6+,你应该使用epoll。如果你使用BSD,你应该使用kqueue。
  • worker_connections:设置可由一个worker进程同时打开的最大连接数。如果设置了上面提到的worker_rlimit_nofile,我们可以将这个值设得很高。记住,最大客户数也由系统的可用socket连接数限制(~ 64K),所以设置不切实际的高没什么好处。

HTTP 模块

HTTP模块控制着nginx http处理的所有核心特性,内容比较多,这里分批说明。

http{
server_tokens off; #开启或关闭在错误信息的“Server”响应头中输出nginx版本号
include mime.types; #文件扩展名与文件类型映射表
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; #设置读取客户端请求超大请求的缓冲最大number(数量)和每块缓冲的size(容量)
client_max_body_size 8m; #设定请求缓存
sendfile on; #开启高效文件传输模式
autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
tcp_nopush on; #开启或者关闭nginx在FreeBSD上使用TCP_NOPUSH套接字选项
tcp_nodelay on; #开启或关闭nginx使用TCP_NODELAY选项的功能
keepalive_timeout 120; #长连接超时时间,单位是秒
reset_timedout_connection on; #开启或关闭重置超时连接的功能
...
}

可以微调的配置:

  • sendfile:指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
  • tcp_nopush: 选项仅在使用sendfile的时候才开启。告诉nginx在一个数据包里发送所有头文件,而不一个接一个的发送。
  • tcp_nodelay:这个选项仅在将连接转变为长连接的时候才被启用。告诉nginx不要缓存数据,而是一段一段的发送——当需要及时发送数据时,就应该给应用设置这个属性,这样发送一小块数据信息时就不能立即得到返回值。
  • reset_timedout_connection:重置连接是这样执行的:关闭套接字以前,设置SO_LINGER选项的超时值为0, 那么当关闭套接字时,nginx向客户端发送TCP RST,并且释放此套接字占用的所有内存。 这样可以避免某个已关闭的套接字长时间处于FIN_WAIT1状态,并占用内存缓冲区。应该注意的事,超时的长连接仍然是正常关闭。
  • client_header_buffer_size:设置读取客户端请求头部的缓冲容量。 对于大多数请求,1K的缓冲足矣。 但如果请求中含有的cookie很长,或者请求来自WAP的客户端,可能请求头不能放在1K的缓冲中。 如果从请求行,或者某个请求头开始不能完整的放在这块空间中,那么nginx将按照 large_client_header_buffers指令的配置分配更多更大的缓冲来存放。
  • large_client_header_buffers:HTTP请求行的长度不能超过一块缓冲的容量,否则nginx返回错误414 (Request-URI Too Large)到客户端。 每个请求头的长度也不能超过一块缓冲的容量,否则nginx返回错误400 (Bad Request)到客户端。 缓冲仅在必需是才分配,默认每块的容量是8K字节。 即使nginx处理完请求后与客户端保持入长连接,nginx也会释放这些缓冲。

gzip模块设置

gzip on; #开启gzip压缩输出
gzip_min_length 1k; #最小压缩长度
gzip_buffers 4 16k; #压缩缓冲区
gzip_http_version 1.0; #压缩版本
gzip_comp_level 2; #压缩等级
gzip_types text/plain application/x-javascript text/css application/xml; #压缩类型。
limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用
upstream 127.0.0.1 { #负载均衡
server 192.168.80.121:80 weight=3;
server 192.168.80.122:80 weight=2;
server 192.168.80.123:80 weight=3;
}

可以微调的配置:

  • upstream:upstream负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。

虚拟主机的配置

server{
listen 80; #监听端口
server_name www.cainiao.com cainiao.com; #域名可以有多个,用空格隔开
 
location / { #对 "/" 启用反向代理
proxy_pass 127.0.0.1:8080; #设置后端服务器的协议和地址
#root /home/admin/pac; #请求根目录
#index index.html index.htm; #主页
 
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Real-IP $remote_addr; 
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配置文件详解

//定义一个用户以及对应的组

user admin admin 

//定义nginx worker 进程的数量,设置为auto,就是默认和CPU个数一致

work_processess auto 

//与上面的指令协同工作。他可以让你的worker进程影响CPU内核,数字序列和work进程一样多

work_cpu_affinity auto 


//nginx错误日志,有debug,warn, error等五个等级

error_log /home/admin/web/logs/error.log warn 

//用于存放nginx守护进程的PID文件路径, 里面记录了主进程的pid号

pid /home/admin/nginx/logs/nginx-search.pid; 

//定义每个work进程的内核文件大小

worker_rlimit_core 1024M

 //定义一个worker进程可以同时处理的文件数量

worker_rlimit_nofile 100000 

 //与events模块一起提供的指令可以用来配置网络机制,指令参数对nginx性能产生影响

events{ 
 //定义一个worker进程能够同时连接的数量
 worker_connectins 10240; 
 use epoll; 
 }


//该区段嵌入配置文件的根部,在该区段允许定义指令和嵌入HTTP相关模块

-http{

 //隐藏nginx的版本号, 出现400 500 页面时候不会显示nginx服务器的版本号,避免漏洞

 server_token off; 

 //文件包含指令; mime.type文件里面保存了nginx的MIME类型; 里面其实也是一个types{...}

 include mime.type

 // 该指令允许你在MIME类型和文件扩展名之间建立联系, 可以补充mime.type文件没有对应关系

 types{ 

 application/x-compress .Z; 
 application/x-gzip .gz .tgz;

 application/x-httpd-php .php .html;

 }

 //定义默认的MIME类型,如果文件扩展名与mime.type中类型都不匹配,就将该值写进content-type

 default_type text/plain;

 //如果该指令被启用,Nginx将使用sendFile 内核来调用文件传递。如果禁用,那么nginx将自己处理文件传递

 sendfile on; 

 //该选项只用于sendfile已启动的情况。若为on, 那么nginx将尝试单个TCP数据包中发送整个HTTP响应头

 tcp_nopush on; 
 

 //keep-alive能够使客户端到服务器的链接在一定时间内持续有效,在这个时间内,客户端对服务器的访问不需要再次建立链接

 keepalive_timeout 0; 

 client_header_timeout 30s; 

 //指定持有客户端请求主体的缓存大小,如果超过这个大小,那么主体将被写到磁盘

 client_body_buffer_size 32k; 


 /**gzip是一种压缩技术。经过gzip压缩后页面大小可以变为原来的30%甚至更小**/

 //开启gzip模块 off为关闭

 gzip on; 

 //识别http的协议版本

 gzip_http_version 1.0; 

 //gzip压缩比,1压缩比最小,9压缩比最大,相应的速度也会变慢

 gzip_comp_level 6; 

 // 设置允许压缩的页面最小字节数,默认为0,页面多大都压缩

 gzip_min_length 1024; 

 //启用或者禁用gzip压缩,针对代理服务器上接收到的相应体

 gzip_proxied any; 

 //有的浏览器支持压缩,有的不支持,为了避免浪费,根据HTTP头来判断是否需要压缩

 gzip_vary on;

 gzip_disable msie6; //???

 //设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流

 gzip_buffers 64 8k; 

 //匹配mime类型进行压缩,无论是否制定“text/html”类型总会被压缩

 gzip_types text/xml text/plain text/css application/javascript application/x- javascript application/rss+xml; 


 //定义文档的根目录,该目录包含你希望为访问者提供的内容

 root /home/admin/web/htdocs; 

 //定义一个默认的页面,如果请求中没有指定文件名,nginx就会使用该页面提供服务。

 index index.html index.php index.htm; 
 //proxy_set_header nginx作为反向代理服务器,将请求转发给后端真实服务器,如果不行host的重写,所有的真是服务器都会误认为是nginx服务器发送的请求。 proxy_set_header就是用于将客户端真实的host, ip信息,传送给后端服务器。 http://www.ithov.com/linux/109626_3.shtml

 proxy_set_header Host $host;

 //在这里X-Real-IP是一个自定义的变量名,名字可以随意取,在web端可以用request.getAttribute("X-Real-IP") 获取IP 
 proxy_set_header X-Real-IP $remote_addr;

 proxy_set_header Web-Server-Type nginx; 

 // 如果需要修改从被代理服务器传来的应答头中的”Location”和”Refresh”字段,可以用指令设置。 

 proxy_redirect off; 
 proxy_buffers 128 8k; 
 proxy_intercept_errors on;
 

 //开启或者禁用404没有找到HTTP错误。例如,如果日志中充满了404错误,却由于 robots.txt文件,那么你可以将这个选项关闭掉;

 log_not_found off;
 

 // 用于定义发生制定的错误代码时候,使用errror_page来定义服务器的行为。最简单的形式是使用一个错误代码改变URI

 error_page 403 404 405 http://www.jd.com/home/error.php;

 error_page 500 501 502 http://www.jd.com/home/error2.php;

 expires_by_types modified +3y image/gif image/jpeg image/jpg text/css application/x-shockwave-flash; 

 //限制被定义的zone的请求总数,$binary_remote_addr用于区分客户端, rate表示每秒的请求数(r/s)或者每分钟请求数(r/m)
 limit_req_zone $binary_remote_addr zone=one:100m rate=5r/s;


 #virtual servers 

 server{

 //指定用于提供web服务站点监听的套接字所使用的IIP和端口 

 listen 80; 

 //在server区段指定一个或者多个主机名(hostname), Nginx接收到HTTP请求以后,会与所有server区段相比较,然后找到与客户端请求header中Host匹配的server区段。如果没有与客户端匹配的server区段,nginx会选择第一个server区段。该指令接受通配符 

 server_name wenda.taobao.com q.etao.com wenda.etao.com;
 

 // 定义一个日志模板用于描述访问日志中一条包含的内容,该模板由access_log指令使用 

 log_format eformat ' remoteaddr r e m o t e a d d r request_time_usec remoteuser[ r e m o t e u s e r [ time_local] ' '"requestmethodhttp:// r e q u e s t m e t h o d h t t p : / / hostrequesturi" r e q u e s t u r i " status $body_bytes_sent ' 

 '" httpreferer"" h t t p r e f e r e r "" http_user_agent"';

 //该指令定了访问日志文件的路径

 access_log "pipe: /opt/taobao/install/cronolog/sbin/cronolog /home/admin/web/logs/search/%Y/%m/%d/access-%Y-%m-%d_%H.log" eformat; 
 

 //定义文档的根目录,该目录包含你希望为访问者提供的内容 

 root /home/admin/web/htdocs/; 

 //limit_req_one 同上,burst定义了最大可能的突发请求, 在一定程度上,burst定义的值就是只能同时接受最大数量的请求值 

 limit_req zone=one burst=5 nodelay; 

 

 //set_by_lua指令支持通过一小段用户Lua代码来计算出一个结果,然后复制给Nginx 变量,和set指令相似

 //Lua代码中,通过ngx.var.VARIABLE来读取Nginx的变量; 下面的一段代码是用于修复comons-fileupload-1.0版本的漏洞

 set_by_lua invalid_ct 'local ct = ngx.var.http_content_type if ct and #ct >= 2049 then return 1 else return 0 end'; if ( invalid_ct 'local ct = ngx.var.http_content_type if ct and #ct >= 2049 then return 1 else return 0 end'; if ( invalid_ct = '1') { return 400; }

 

 //根据host 进行跳转的判断 

 if ($host = 'q.jd.com'){

 //该指令允许你对当前请求的URI 进行重写,因此对客户端的请求会被重新设置

 //格式为 rewrite regexp replacement 【flag】 ;; flag 包含:last, break,redirect, permanent

 // regexp 是URI正则表达式,他的目的是匹配后面的replacement 

 //permanent 返回301 重定向响应,被替代的URI作为location头的值(浏览器显示跳转之后URL地址)

 rewrite ^/(.*) http://wenda.jd.com/ http://wenda.jd.com/1 permanent; 
 }

 

 location ~ .(do|htm|vhtml|service|jhtml)$ {
 //在配置proxy_pass的时候需要注意:http://dmouse.iteye.com/blog/1880474
 //符合location 样式跳转地址; 这个指令设置被代理服务器的地址和被映射的URI,地址可以使用主机名或IP加端口号的形式。
 proxy_pass http://127.0.0.1:8000;

 //拒绝访问的IP字段
 	deny 113.59.*.*; 
 }

}

更多参考

更详细的模块参数请参考:http://nginx.org/cn/docs/

核心模块:http://nginx.org/cn/docs/http/ngx_http_core_module.html

总结

作者:北极象原文地址:https://blog.csdn.net/jgku/article/details/128663108

%s 个评论

要回复文章请先登录注册