Nginx总结.md

基本配置

注意:下面的nginx版本是1.10,安装是在CentOS 7中通过epel源进行安装的nginx默认配置文件。

# egrep -v "(^$)|(^#)|#" /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
    worker_connections 1024;
}
http {
    log_format  main  '$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.log  main;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    include /etc/nginx/conf.d/*.conf;
    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;
        include /etc/nginx/default.d/*.conf;
        location / {
        }
        error_page 404 /404.html;
            location = /40x.html {
        }
        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}

下面是基于上面的配置文件进行初步的优化:

# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log logs/error.log notice;
pid /var/run/nginx.pid;
worker_	rlimit_nofile 20480;
worker_cpu_affinity auto;
events {
accept_mutex on;  #不建议开启
use epoll;  #默认会使用最有效的方法
multi_accept on;
worker_connections 20480;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
sendfile on
server_tokens off;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
	server {
	listen 80;
	server_name localhost;
	charset utf-8;
		location / {
		root html;
		index index.html;
		}
	error_page 500 502 503 504 /50x.html;
		location = /50x/html {
		root html;
		}
	}
}

常用配置

虚拟主机与静态站点

静态站点配置

1.listen:设置nginx监听的IP地址和端口,如果不指定IP地址则监听在该机器的所有IP地址上,同时可以使用default_server来设置默认虚拟主机, ssl用于限制只能通过ssl连接提供服务。
2.server_name:设置虚拟主机的名,其后可以跟一个或者多个主机名,主机名称可以使用通配符和正则表达式。在匹配时首先是精确匹配,其次是左侧通配,然后死右侧通配,最后是正则。
3.index:定义默认主页的格式。
4.root:设置请求的根目录。
5.error_page:定义错误提示页面。

 server {
        listen       80 default_server;
        #listen       [::]:80 default_server;
        server_name  www.study.com;
        access_log   /var/log/nginx/study_access.log main;

        location / {
        index        index.html index.htm;
        root         /data/website/study;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

测试

[root@study html]# tree /data/website/
/data/website/
└── study
    ├── 404.html
    ├── 50x.html
    └── index.html

1 directory, 3 files
# curl www.study.com 
study.com

alias

定义指定位置的替换。路径值可以包含变量,$document_root和$ realpath_root除外。如果在使用正则表达式定义的位置内使用别名,则此类正则表达式应包含捕获,并且别名应引用这些捕获。
举例

location /test {
  root /data/website;
}

# curl http://www.a.com/test/
/data/website/test/

root指令:给定的路径对应于location的“/”这个URL;
/test/index.html --> /data/website/test/index.html
alias指令:给定的路径对应于location的“/uri/"这个URL;
/test/index.html --> /data/website/index.html

error_page

根据http状态码重定向错误页面。
举例

location / {
  root /data/website;
}
error_page  404              /404.html
# echo 404.page >/data/website/404.html
# curl http://www.a.com/aaaaa
404.page
# curl http://www.a.com/aaaaa -I
HTTP/1.1 404 Not Found
Server: nginx/1.10.1
Date: Sat, 11 Feb 2017 16:39:24 GMT
Content-Type: text/html
Content-Length: 9
Connection: keep-alive
ETag: "589f3e1d-9"

try_files

尝试查找第1至第N-1个文件,第一个即为返回给请求者的资源;若1至N-1文件都不存在,则跳转至最一个uri(必须不能匹配至当前location,而应该匹配至其它location,否则会导致死循环);
举例

  root /data/website;
       location /test {
  try_files /test/1.html /test/2.html /test/3.html @abc;
}
     location @abc {
      rewrite ^/(.*)$ http://baidu.com;
}
# ls /data/website/test/
3.html
# curl http://www.a.com/test/1.html
33333

location资源匹配

location  = / {
  # 精确匹配 / ,主机名后面不能带任何字符串
  [ configuration A ]
}
location  / {
  # 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求
  # 但是正则和最长字符串会优先匹配
  [ configuration B ]
}
location /documents/ {
  # 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
  # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
  [ configuration C ]
}
location ~ /documents/Abc {
  # 匹配任何以 /documents/Abc 开头的地址,匹配符合以后,还要继续往下搜索
  # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
  [ configuration CC ]
}
location ^~ /images/ {
  # 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。
  [ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
  # 匹配所有以 gif,jpg或jpeg 结尾的请求
  # 然而,所有请求 /images/ 下的图片会被 config D 处理,因为 ^~ 到达不了这一条正则
  [ configuration E ]
}
location /images/ {
  # 字符匹配到 /images/,继续往下,会发现 ^~ 存在
  [ configuration F ]
}
location /images/abc {
  # 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在
  # F与G的放置顺序是没有关系的
  [ configuration G ]
}
location ~ /images/abc/ {
  # 只有去掉 config D 才有效:先最长匹配 config G 开头的地址,继续往下搜索,匹配到这一条正则,采用
    [ configuration H ]
}

1.=开头表示精确匹配,如 A 中只匹配根目录结尾的请求,后面不能带任何字符串。
2.^~ 开头表示uri以某个常规字符串开头,不是正则匹配。
3.~ 开头表示区分大小写的正则匹配;
4.~* 开头表示不区分大小写的正则匹配
5./ 通用匹配, 如果没有其它匹配,任何请求都会匹配到

顺序 no优先级:
(location =) > (location 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (/)

上面的匹配结果
按照上面的location写法,以下的匹配示例成立:

/ -> config A
精确完全匹配,即使/index.html也匹配不了
/downloads/download.html -> config B
匹配B以后,往下没有任何匹配,采用B
/images/1.gif -> configuration D
匹配到F,往下匹配到D,停止往下
/images/abc/def -> config D
最长匹配到G,往下匹配D,停止往下
你可以看到 任何以/images/开头的都会匹配到D并停止,FG写在这里是没有任何意义的,H是永远轮不到的,这里只是为了说明匹配顺序
/documents/document.html -> config C
匹配到C,往下没有任何匹配,采用C
/documents/1.jpg -> configuration E
匹配到C,往下正则匹配到E
/documents/Abc.jpg -> config CC
最长匹配到C,往下正则顺序匹配到CC,不会往下到E

http://seanlook.com/2015/05/17/nginx-location-rewrite/

MIME类型相关的配置

1.default_type:定义响应的默认MIME类型。可以使用types指令来将文件扩展名映射到MIME类型。
2.types:将文件扩展名映射到MIME类型的响应。扩展名不区分大小写。在nginx配置文件中有个mime.types文件是nginx默认的映射表。要使用特定位置发出所有请求的“application/octet-stream”MIEM类型,可以使用如下配置:

location /download/ {
    types        { }
    default_type application/octet-stream;
}

3.types_hash_bucket_size:设置类型哈希表的存储bucket大小。
4.types_hash_max_size:设置类型哈希表的最大大小。

防盗链

1.referer_hash_bucket_size:设置有效的查阅器哈希表的bucket大小。
2.referer_hash_max_size:设置有效的查阅器哈希表最大大小。
3.valid_referers:指定“Referer”请求字段值,这将导致嵌入的$invalid_referer变量设置为空字符串。搜索匹配不区分大小写。

valid_referers选项
1.none:请求头中缺少“Referer”字段;
2.blocked:“请求”字段存在于请求标头中,但其值已被防火墙或代理服务器删除; 这样的值是不以“http://”“https://”开头的字符串;
3.server_names:“Referer”请求头字段包含服务器名称之一;
4.arbitrary string:定义服务器名称和可选的URI前缀。 服务器名称的开头或结尾可以有“*”。 在检查期间,“Referer”字段中的服务器端口被忽略;
5.regular expression:第一个符号应该是一个“〜”。 应当注意,表达式将与在“http://”“https://”之后开始的文本匹配。

举例

location ~* \.(gif|png|jpg|bmp)$ {
        valid_referers none blockd *.study.com;
        if ($invalid_referer) {
           rewrite ^/ http://www.study.com/fuck.html;
          }
       }

headers模块

1.add_header:如果响应码等于200、201、204、206、301、302、303、304或307,则将指定的字段添加到响应头中。这里需要注意:在使用此指令时只能添加报头而不能重写报头。
2.expires:如果响应代码等于200,201,204,206,301,302,303,304或307,则启用或禁用添加或修改“Expires”和“Cache-Control”响应头字段

举例

        location / {
        add_header   X-Via $server_addr;
        index        index.html index.htm;
        root         /data/website/study;
        }
        location ~* \.(gif|png|jpg|bmp)$ {
          expires 30d;
       }

ssl

1.ssl:为指定的虚拟主机启用HTTPS协议。建议使用listen指令的ssl参数。
2.ssl_buffer_size:设置用于发送数据的缓冲区大小。
3.ssl_certificate:指定开启HTTPS协议主机的PEM格式证书文件。从版本1.11.0开始,可以多次指定此伪指令来加载不同类型的证书,只有OpenSSL 1.0.2或更高版本支持不同证书的单独证书链。 对于旧版本,只能使用一个证书链。由于HTTPS协议的限制,虚拟服务器应该在不同的IP地址上侦听,否则将为第二个站点发出第一个服务器的证书。
4.ssl_certifirate_key:指定具有给定虚拟服务器的PEM格式的密钥的文件。
5.ssl_ciphers:指定启用的密码。 密码以OpenSSL库理解的格式指定。
6.ssl_protocols:启用指定的协议。 仅当使用版本1.0.1或更高版本的OpenSSL库时,TLSv1.1和TLSv1.2参数才起作用。从版本1.1.13和1.0.12开始支持TLSv1.1和TLSv1.2参数,因此,当旧版nginx版本使用OpenSSL版本1.0.1或更高版本时,这些协议可以正常工作,但不能禁用。
7.ssl_session_cache:设置存储会话参数的高速缓存的类型和大小。
8.ssl_session_timeout:客户端可以重用会话缓存中ssl参数的过期时间。
9.ssl_prefer_server_ciphers:设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。

ssl_session_cache选项说明
1.off:严格禁止使用会话缓存:nginx显式告诉客户端会话可能不会被重用。
2.none:缓慢地禁止使用会话缓存:nginx告诉客户端会话可以被重用,但实际上不在高速缓存中存储会话参数。
3.builtin:一个内置在OpenSSL中的缓存; 仅由一个工作进程使用。 缓存大小在会话中指定。 如果未指定大小,则等于20480个会话。 使用内置缓存可能会导致内存碎片。
4.shared:在所有工作进程之间共享的高速缓存。 缓存大小以字节为单位指定; 一兆字节可以存储约4000个会话。 每个共享缓存应该有一个任意名称。 具有相同名称的缓存可用于多个虚拟服务器。

两种缓存类型可以同时使用,例如:

ssl_session_cache builtin:1000 shared:SSL:10m;

但是只使用没有内置缓存的共享缓存应该更有效。
举例

server {
        listen 443 ssl;
        server_name ssl.study.com;
        ssl_certificate "/etc/nginx/ssl/study.crt";
        ssl_certificate_key "/etc/nginx/ssl/study.key";
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;

        location / {
          root /data/website/study/ssl;
          index index.html index.htm;
         }
}

扩展学习
1.自签ssl证书时有时会遇到如下问题:

Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
The organizationName field needed to be the same in the
CA certificate (ca.com) and the request (study.com)

具体解决方法我是将/etc/pki/tls/openssl.cnf文件中countryName = optionalstateOrProvinceName = optionalorganizationName = optional这个三个参数修改。
2.由于使用HTTPS会非常消耗CPU资源,这里建议开启keepalive、ssl_session_cache和ssl_session_timeout功能提升性能。其中1M 的会话缓存大概包含 4000 个会话,而默认的ssl_session_timeout为5m,我们可以设置增加时间。
3.可是使用 HSTS 策略强制浏览器使用 HTTPS 连接,这个需要做好全站HTTPS才能申请。但是加入后清除比较麻烦,这个需要注意。
4.nginx在1.1.13和1.0.12版本后默认是ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2,TLSv1.1与TLSv1.2要确保OpenSSL >= 1.0.1 ,SSLv3 现在还有很多地方在用但有不少被攻击的漏洞。

https://luckymrwang.github.io/2015/10/09/Nginx-SSL-性能优化/
https://aotu.io/notes/2016/08/16/nginx-https/
http://seanlook.com/2015/05/28/nginx-ssl/

log

1.log_not_found:启用或者禁用将未找到的文件记录到error_log中。默认开启。
2.log_subrequest:启用或者禁用将子请求记录到access_log中。默认关闭。
3.access_log:设置缓冲日志写入的路径,格式和配置。
4.log_format:指定日志格式。
5.open_log_file_cache:定义一个缓存,用于存储其名称包含变量的常用日志的文件描述符。默认关闭。
6.rewrite_log:启用或禁用将ngx_http_rewrite_module模块伪指令的处理结果记录到通知级别的error_log。默认关闭。
7.error_log:配置错误日志。第一个参数定义将存储日志的文件。第二个参数确定日志记录的级别,可以是以下之一:debug,info,notice,warn,error,crit,alert或emerg。 以上的日志级别按严重性递增的顺序列出。

access_log参数
1.gzip压缩等级。
2.buffer设置内存缓存区大小。
3.flush保存在缓存区中的最长时间。
4.off不记录日志。

比如,设置 buffer,buffer 满 32k 才刷盘;假如 buffer 不满 5s 钟强制刷盘的配置如下:

access_log /var/log/nginx/access.log buffer=32k flush=5s;

log_format日志格式

变量含义
$remote_addr client address
$remote_user 用户名提供基本认证
$time_local 公共日志格式中的本地时间
$request 记录请求的URL和HTTP协议
$status response status
$body_bytes_sent 发送到客户端的字节数,不计数响应头
$http_referer url跳转来源
$http_user_agent 用户端浏览器信息
$http_x_forwarded_for 记录客户端IP地址
$bytes_sent 发送到客户端的字节数
$connection 连接序列号
$connection_requests 通过连接发出的当前请求数
$msec 日志写入时间。单位为秒,精度是毫秒。
$pipe 如果请求是通过HTTP流水线(pipelined)发送,pipe值为“p”,否则为“.”。
$request_length 请求的长度(包括请求行,请求头和请求正文)。
$request_time 请求处理时间,单位为秒,精度毫秒; 从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。

open_log_file_cache参数
1.max:设置缓存中的最大文件描述符数量,如果缓存被占满,采用LRU算法将描述符关闭。
2.inactive:设置存活时间,默认是10s
3.min_uses:设置在inactive时间段内,日志文件最少使用多少次后,该日志文件描述符记入缓存中,默认是1次
4.valid:设置检查频率,默认60s

rewrite

1.break:停止处理当前的ngx_http_rewrite_module伪指令集。
2.if:评估指定的条件。 如果为true,那么在大括号中指定的模块指令将被执行,并且请求被分配在if指令内部的配置。 if指令内的配置继承自先前的配置级别。
3.return:停止处理并将指定的代码返回给客户端。
4.rewrite:如果指定的正则表达式匹配请求URI,那么将按照替换字符串中指定的方式更改URI。 重写指令按照它们在配置文件中的出现顺序执行。 可以使用标志来终止指令的进一步处理。 如果替换字符串以“http://”“https://”“$ scheme”开头,则处理停止,并将重定向返回给客户端。
5.set:设置指定变量的值。 该值可以包含文本,变量及其组合。
6.uninitialized_variable_warn:控制是否记录警告未初始化的变量。

if使用

1.变量名;如果变量的值为空字符串或“0”,则为false;在版本1.0.1之前,以“0”开头的任何字符串被视为false值。
2.使用“=”和“!=”运算符将变量与字符串进行比较;
3.~:模式匹配,区分字符大小写;~*:模式匹配,不区分字符大小写;!~:模式不匹配,区分字符大小写;!~*: 模式不匹配,不区分字符大小写;
4.使用“-f”和“!-f”运算符检查文件存在;
5.使用“-d”和“!-d”运算符检查目录存在;
6.使用“-e”和“!-e”运算符检查文件,目录或符号链接是否存在;
7.使用“-x”和“!-x”运算符检查可执行文件。

rewrite使用

1.last:停止处理当前的ngx_http_rewrite_module指令集,并开始搜索与更改的URI匹配的新位置;
2.break:停止处理当前的ngx_http_rewrite_module指令集,如同break指令一样;
3.redirect:返回具有302代码的临时重定向; 如果替换字符串不以“http://”“https://”“$ scheme”开头,则使用;
4.permanent:返回301代码的永久重定向。

举例
多目录转成参数:
abc.domian.com/sort/2 => abc.domian.com/index.php?act=sort&name=abc&id=2

if ($host ~* (.*)\.domain\.com) {
set $sub_name $1;   
rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&cid=$sub_name&id=$1 last;
}

目录对换
/123456/xxxx -> /xxxx?id=123456

rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;

例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下:

if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /nginx-ie/$1 break;
}

目录自动加“/”

if (-d $request_filename){
rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
}

将多级目录下的文件转成一个文件,增强seo效果
/job-123-456-789.html 指向/job/123/456/789.html

rewrite ^/job-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /job/$1/$2/jobshow_$3.html last;

https://xuexb.com/html/nginx-url-rewrite.html
http://www.tiyee.net/post/122
http://blog.c1gstudio.com/archives/434

fastcgi

1.fastcgi_pass:设置FastCGI服务器的地址。 地址可以指定为域名或IP地址和端口:fastcgi_pass localhost:9000。如果域名解析为多个地址,则所有这些地址都将以循环方式使用。 此外,可以将地址指定为服务器组。
2.fastcgi_index:在$ fastcgi_script_name变量的值中设置将附加在以斜杠结尾的URI后面的文件名。 例如,使用这些设置和“/page.php”请求,SCRIPT_FILENAME参数将等于“/home/www/scripts/php/page.php”,对于“/”请求,它将等于“/home/www/scripts/php/index.php“
3.fastcgi_param:设置应传递到FastCGI服务器的参数。 该值可以包含文本,变量及其组合。 当且仅当没有在当前级别上定义fastcgi_param伪指令时,这些伪指令才继承自上一级。
4.fastcgi_cache_path:设置缓存的路径和其他参数。 缓存数据存储在文件中。 高速缓存中的密钥和文件名都是将MD5函数应用于代理URL的结果。 levels参数定义缓存的层次结构级别:从1到3,每个级别接受值1或2.例如,在以下配置中:fastcgi_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;缓存中的文件名将如下所示:/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
5.fastcgi_cache:定义用于缓存的共享内存区域。 同一区域可以在几个地方使用。 参数值可以包含变量(1.7.9)。 off参数禁用从先前配置级别继承的缓存。
6.fastcgi_cache_key:定义用于缓存的键。
7.fastcgi_cache_methods:如果客户端请求方法列在此指令中,那么响应将被缓存。 “GET”和“HEAD”方法总是添加到列表中,但建议明确指定它们。
8.fastcgi_cache_min_uses:设置在其后响应将被缓存的请求数。
9.fastcgi_cache_use_stable:确定在与FastCGI服务器通信期间发生错误时,可以使用过时缓存响应的情况。默认禁用。
10.fastcgi_cache_valid:设置不同响应代码的缓存时间。
11.fastcgi_connect_timeout:定义与FastCGI服务器建立连接的超时。 应该注意,该超时通常不能超过75秒。
12.fastcgi_send_timeout:设置将请求发送到FastCGI服务器的超时。 超时仅在两个连续的写操作之间设置,而不是用于传输整个请求。 如果FastCGI服务器在此时间内未收到任何内容,则连接将关闭。
13.fastcgi_read_timeout:定义从FastCGI服务器读取响应的超时。 超时仅在两个连续读取操作之间设置,而不是用于传输整个响应。 如果FastCGI服务器在此时间内未传输任何内容,则连接将关闭。
14.fastcgi_buffer_size:设置用于读取从FastCGI服务器接收的响应的第一部分的缓冲区大小。 这部分通常包含一个小的响应报文header。 默认情况下,缓冲区大小等于一个内存页。是4K或8K,取决于平台。 然而,它可以做得更小。
15.fastcgi_buffers:设置用于从FastCGI服务器读取单个连接的响应的缓冲区的数量和大小。 默认情况下,缓冲区大小等于一个内存页。 是4K或8K,取决于平台。
16.fastcgi_busy_buffers_size:当启用来自FastCGI服务器的响应缓冲时,限制可能响应报文尚未完全读取而忙于向客户端发送响应的缓冲区的总大小。 同时,其余缓冲区可用于读取响应,并且如果需要,缓冲对临时文件的响应的一部分。 默认情况下,大小受限于由fastcgi_buffer_size和fastcgi_buffers指令设置的两个缓冲区的大小。
17.fastcgi_buffering:启用或禁用来自FastCGI服务器的响应报文缓冲。
18.fastcgi_temp_file_write_size:当启用从FastCGI服务器到临时文件的响应缓冲时,限制写入临时文件的数据大小。 默认情况下,大小受限于由fastcgi_buffer_size和fastcgi_buffers指令设置的两个缓冲区。 临时文件的最大大小由fastcgi_max_temp_file_size指令设置。
19.fastcgi_max_temp_file_size:当启用来自FastCGI服务器的响应缓冲,并且整个响应不适合由fastcgi_buffer_size和fastcgi_buffers指令设置的缓冲区时,响应的一部分可以保存到临时文件。 此伪指令设置临时文件的最大大小。 一次写入临时文件的数据大小由fastcgi_temp_file_write_size指令设置。
20.fastcgi_temp_path:定义用于存储具有从FastCGI服务器接收的数据的临时文件的目录。 最多可以在指定目录下使用三级子目录层次结构。

举例

http {
    include       mime.types;
    default_type  application/octet-stream;
	sendfile        on;
	keepalive_timeout  65;
	fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=fcgicache:10m;
	server {
        listen       80;
        server_name  www.a.com;
		location / {
		root html;
		index  index.html index.htm;
		}
        location ~ \.php$ {
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_cache  fcgicache;
            fastcgi_cache_key $request_uri;
            fastcgi_cache_valid 200 302 10m;
            fastcgi_cache_valid 301      1h;
            fastcgi_cache_valid any      1m;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /usr/share/nginx/html/$fastcgi_script_name;
            include        fastcgi_params;
        }
    }
}
没有启用缓存的测试:
# ab -c 100 -n 1000 http://www.a.com/info.php
···
Requests per second:    1299.63 [#/sec] (mean)
Time per request:       76.945 [ms] (mean)
Time per request:       0.769 [ms] (mean, across all concurrent requests)
Transfer rate:          48288.03 [Kbytes/sec] received
···
启用缓存的测试:
# ab -c 100 -n 1000 http://www.a.com/info.php
...
Requests per second:    7686.87 [#/sec] (mean)
Time per request:       13.009 [ms] (mean)
Time per request:       0.130 [ms] (mean, across all concurrent requests)
Transfer rate:          285607.67 [Kbytes/sec] received
...

注意
1.创建缓存最少需要定义四个指令:fastcgi_cache_path、fastcgi_cache_key、fastcgi_cache_valid、fastcgi_cache。
2.缓存定义的目录需要手动创建。

反向代理

1.proxy_pass:设置代理服务器的协议和地址以及应映射位置的可选URI。 作为协议,可以指定“http”或“https”。
2.proxy_set_header:用于proxy server向backend server发请求报文时,将某请求首部重新赋值,或在原有值后面添加一个新的值; 也可以添加自定义首部;
3.proxy_cache_path:设置缓存的路径和其他参数。 缓存数据存储在文件中。 高速缓存中的文件名是将MD5函数应用于高速缓存密钥的结果。 levels参数定义缓存的层次结构级别:从1到3,每个级别接受值1或2.
4.proxy_cache_key:定义用于缓存的键。
5.proxy_cache_valid:设置不同响应代码的缓存时间。
6.proxy_connect_timeout:定义与代理服务器建立连接的超时。 应该注意,该超时通常不能超过75秒。
7.proxy_send_timeout:设置将请求传输到代理服务器的超时。 超时仅在两个连续的写操作之间设置,而不是用于传输整个请求。 如果代理服务器在此时间内未收到任何内容,则连接将关闭。
8.proxy_read_timeout:定义从代理服务器读取响应的超时。 超时仅在两个连续读取操作之间设置,而不是用于传输整个响应。 如果代理服务器在此时间内未发送任何内容,则连接将关闭。
9.proxy_buffer_size:设置用于读取从代理服务器接收的响应的第一部分的缓冲区大小。 这部分通常包含一个小的响应头。 默认情况下,缓冲区大小等于一个内存页。 这是4K或8K,取决于平台。 然而,它可以做得更小。
10.proxy_buffering:启用或者禁用proxy 缓冲。
11.proxy_buffers:设置用于从代理服务器读取单个连接的响应的缓冲区的数量和大小。 默认情况下,缓冲区大小等于一个内存页。 这是4K或8K,取决于平台。
12.proxy_busy_buffers_size:当启用来自代理服务器的响应缓冲时,限制可能忙于向客户端发送响应的缓冲区的总大小,而响应尚未完全读取。 同时,其余缓冲区可用于读取响应,并且如果需要,缓冲对临时文件的响应的一部分。 默认情况下,大小受由proxy_buffer_size和proxy_buffers指令设置的两个缓冲区的大小的限制。
13.proxy_cache_methods:如果客户端请求方法列在此指令中,那么响应将被缓存。 “GET”和“HEAD”方法总是添加到列表中,但建议明确指定它们。 另请参见proxy_no_cache指令。
14.proxy_no_cache:定义响应不会保存到缓存的条件。 如果字符串参数的至少一个值不为空,并且不等于“0”,则不会保存响应。
15.proxy_cache_min_uses:设置在其后响应将被缓存的请求数。

举例
proxy_pass后面的路径不带uri时,其会将location的uri传递给后端的主机;下面的示例会将/uri/传递给backend服务器;

location  /uri/ {
	proxy_pass http://hostname;
}

proxy_pass后面的路径是一个uri时,其会将location的uri替换为后端主机自己的uri;

location  /uri/ {
	proxy_pass http://hostname/new_uri/;
}

如果location定义其uri时使用的正则表达式模式匹配,则proxy_pass后的路径不能够使用uri;

location  ~*  \.(jpg|gif|jpeg)$  {
	proxy_pass  http://HOSTNAME;
}

此处的http://HOSTNAME后面不能有任何uri,哪怕只有/也不可以;

关于缓存相关的配置:

proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=proxycache:10m;
location / {
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 301      1h;
proxy_cache_valid any      1m;
proxy_pass http://192.168.0.201/bbs/;
index  index.html index.htm;
}
中间重新载入配置在访问页面进行缓存。
# ll /var/cache/nginx/proxy/
总用量 0
drwx------ 4 nginx nginx 24 2月  20 00:12 9

负载均衡

1.server:定义服务器的地址和其他参数。 可以将地址指定为域名或IP地址,具有可选端口或作为在“unix:”前缀后指定的UNIX域套接字路径。 如果未指定端口,则使用端口80。 解析为多个IP地址的域名会一次定义多个服务器。
2.hash:指定服务器组的负载平衡方法,其中客户端 - 服务器映射基于散列键值。 键可以包含文本,变量及其组合。 请注意,从组中添加或删除服务器可能会导致将大多数密钥重新映射到不同的服务器。
3.ip_hash:指定组应使用负载平衡方法,其中请求根据客户端IP地址分布在服务器之间。 客户端IPv4地址的前三个八位字节或整个IPv6地址用作散列密钥。 该方法确保来自同一客户端的请求将始终传递到同一服务器,除非此服务器不可用。 在后一种情况下,客户端请求将被传递到另一个服务器。 最可能的是,它将始终是相同的服务器。
4.keepalive:激活与上游服务器的连接的缓存。connections参数设置保存在每个工作进程的缓存中的上游服务器的空闲keepalive连接的最大数量。 当超过此数量时,最近使用的最少连接将关闭。应该特别注意的是,keepalive伪指令不限制nginx工作进程可以打开的到上游服务器的连接的总数。 连接参数应设置为足够小,以允许上游服务器处理新的传入连接。

server参数
1.weight=number:设置服务器的权重,默认为1。
2.max_fails=number:设置应在fail_timeout参数设置的持续时间内与服务器通信的失败尝试次数,以考虑服务器在fail_timeout参数设置的持续时间内不可用。 默认情况下,失败尝试次数设置为1.零值禁用尝试计数。
3.fail_timeout=time:与服务器通信的指定次数的失败尝试发生在考虑服务器不可用的时间。以及服务器将被视为不可用的时间段。默认情况下,参数设置为10秒。
4.backup:将服务器标记为备份服务器。 当主服务器不可用时,将传递请求。
5.down将服务器标记为永久不可用。

访问控制

1.limit_conn:设置共享内存区域和给定键值的最大允许连接数。 当超出此限制时,服务器将返回503(服务临时不可用)错误以回复请求。
2.limit_conn_log_level:设置服务器限制连接数时所需的日志记录级别。
3.limit_conn_status:设置要响应拒绝的请求返回的状态代码。
4.limit_conn_zone:设置将保持各种键的状态的共享内存区域的参数。特别地,该状态包括当前连接数。键可以包含文本,变量及其组合。不计入具有空键值的请求。
5.limit_req:设置共享内存区域和请求的最大突发大小。 如果请求速率超过为区域配置的速率,则它们的处理被延迟,使得以定义的速率处理请求。 过多的请求被延迟,直到它们的数量超过最大突发大小,在这种情况下,请求以错误503(服务临时不可用)结束。 默认情况下,最大突发大小等于零。
6.limit_req_log_level:为服务器由于速率超过或拒绝请求处理而拒绝处理请求的情况设置所需的日志记录级别。 延迟的日志级别比拒绝的日志级别低一个点; 例如,如果指定了“limit_req_log_level notice”,则会使用信息级别记录延迟。
7.limit_req_status:设置要响应拒绝的请求返回的状态代码。
8.limit_req_zone:设置将保持各种键的状态的共享内存区域的参数。 特别地,该状态存储当前的过多请求数。 键可以包含文本,变量及其组合。 不计入具有空键值的请求。
9.limit_except:对指定范围之外的其它的方法进行访问控制; 方法参数可以是以下之一:GET,HEAD,POST,PUT,DELETE,MKCOL,COPY,MOVE,OPTIONS,PROPFIND,PROPPATCH,LOCK,UNLOCK或PATCH。
10.limit_rate:限制客户端每秒钟所能够传输的字节数,默认为0表示无限制; 速率以字节/秒指定。这是对每个请求设置限制,因此如果客户端同时打开两个连接,则总速率将是指定限制的两倍。
11.limit_rate_after:设置初始量,在此之后,对客户端的响应的进一步传输将受到速率限制。
12.internal:指定给定位置只能用于内部请求。 * 对于外部请求,返回客户端错误404(找不到)。

举例

客户端请求限制

location /download {
limit_except GET {
  allow 192.168.0.220;
  deny all;
}
}

下载速度限制

location /download {
limit_rate 20480;
}
# wget http://www.a.com/download/test.img
--2017-02-12 01:19:55--  http://www.a.com/download/test.img
正在解析主机 www.a.com (www.a.com)... 192.168.0.220
正在连接 www.a.com (www.a.com)|192.168.0.220|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:209715200 (200M) [application/octet-stream]
正在保存至: “test.img”

 0% [                                                                                                                                                    ] 245,760     20.0KB/s 剩余 2h 50m

请求连接数限制
以下配置将限制每个客户端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;
}

请求速率限制
以下配置将限制来自单个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 zone=perip burst=5 nodelay;
    limit_req zone=perserver burst=10;
}

速率在每秒请求数(r/s)中指定。如果需要每秒小于一个请求的速率,则在每分钟请求中指定(r/m)。例如,每秒半请求为30r/m。

如果不希望在请求受限时延迟过多的请求,则应使用参数nodelay。

缓存

1.open_file_cache:配置nginx存储下面内容的缓存 文件描述符、文件大小和最近一次的修改时间;打开的目录结构;没有找到的或者没有权限操作的文件信息。
2.open_file_cache_errors:是否缓存找不到路径的文件,或者没有权限访问的文件相关信息。
3.open_file_cache_min_uses:设置由open_file_cache指令的inactive参数配置的时间段内文件访问的最小数量。
4.open_file_cache_valid:每隔多久检查一次缓存项的有效性。
举例

open_file_cache max=100000 inactive=20s;  
open_file_cache_valid 30s;  
open_file_cache_min_uses 2;  
open_file_cache_errors on;  

参数说明:
1.max:表示可以缓存的最大条目上限,一旦达到则会使用LRU算法清除最近最少使用的缓存项。
2.inactive:在指定的时长内没有被访问过的缓存项为非活动缓存项,直接删除。
3.off:禁用缓存。

gzip压缩

1.gzip:启用或者停用gzip压缩响应。
2.gzip_buffers:设置用于压缩响应的缓冲区数量和大小。
3.gzip_comp_level:设置gzip压缩级别。接受的的值为1~9之间。
4.gzip_disable:为指定的客户端禁用gzip功能。我们设置成IE6或者更低版本以使我们的方案能够广泛兼容。
5.gzip_min_length:设置gzip压缩的最小长度。长度仅根据“Content-Length”响应头字段确定。
6.gzip_http_version:设置压缩响应所需的请求的最小HTTP版本。
7.gzip_proxied:根据请求和响应启用或者禁用代理请求响应的gzip压缩。
8.gzip_types:除了“text/html”之外,还允许为指定的MIME类型使用gzip压缩。
9.gzip_vary:如果指令gzip,gzip_static或gunzip处于活动状态,则启用或禁用插入“Vary:Accept-Encoding”响应头字段。

举例

    gzip               on;
    gzip_buffers       32 8k;
    gzip_comp_level     6;
    gzip_disable       "msie6";
    gzip_min_length    1k;
    gzip_http_version  1.1;
    gzip_proxied       any;
    gzip_types         text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_vary          on;

关于gzip_proxied指令的参数说明:
1.off:禁用所有代理请求的压缩,忽略其他参数;
2.expired:如果响应头包括具有禁用缓存的值的“Expires”字段,则启用压缩;
3.no-cache:如果响应头包括具有“no-cache”参数的“Cache-Control”字段,则启用压缩;
4.no-store:如果响应头包括具有“no-store”参数的“Cache-Control”字段,则启用压缩;
5.private:如果响应头包括具有“private”参数的“Cache-Control”字段,则启用压缩;
6.no_last_modified:如果响应头不包括“Last-Modified”字段,则启用压缩;
7.no_etag:如果响应报头不包括“ETag”字段,则启用压缩;
8.auth:如果请求头包括“授权”字段则启用压缩;
9.any:启用对所有代理请求的压缩。

auth_basic、stub_status模块

1.auth_basic:启用使用“HTTP Basic Authentication”协议验证用户名和密码。
2.auth_basic_user_file:指定验证的用户名和密码。一般是用htpasswd生成用户和密码。
3.stub_status:显示nginx基本状态信息。
各状态说明
1.Active connections:当前客户端连接数,包括等待连接。
2.accepts:接受的客户端连接的总数。
3.handled:处理的连接的总数。 通常,参数值与accept相同,除非已达到某些资源限制(例如,worker_connections限制)。
4.requests:客户端请求的总数。
5.Reading:nginx正在读取请求头的当前连接数。
6.Writing:nginx正在将响应写回客户端的当前连接数。
7.Waiting:等待请求的空闲客户端连接的当前数量。

举例

        location /nginx_status {
        auth_basic   nginx_status;
        auth_basic_user_file .nginx_user;
        stub_status;
        }
# cat /etc/nginx/.nginx_user 
bols:$apr1$nD1i394h$QZYXyYD1AO5wUgakx9N7X.		
# curl -u bols:bols http://www.study.com/nginx_status
Active connections: 1 
server accepts handled requests
 19 19 34 
Reading: 0 Writing: 1 Waiting: 0 		

优化

main段

1.worker_cpu_affinity:针对多核CPU设置将nginx的worker进程绑定在指定的cpu上。绑定的CPU还是会运行别的进程,如果想要将CPU的核心只运行nginx的worker进程,需要使用taskset命令进行设置。在新版本的1.10中此选项可以使用auto让其自动绑定。
2.worker_priority:定义worker进程的优先级,负数意味着级别高,一般是在-20~19之间选择。一般不建议设置此选项。
3.worker_processes:worker进程的数量,一般是CPU核心数量减1,在新版本1.10可以设置成auto实现自行设定。
4.worker_rlimit_nofile:指定一个worker进程打开的最多文件句柄数。

event段

1.accept_mutex:worker接收请求时的负载均衡锁,启用时可以让worker进程轮流、序列化的接受请求。否则则向所有worker进程通知请求。使用此选项可以避免出现惊群现象,但是如果worker进程比较少则可以不开启此选项。
2.accept_mutex_delay:如果启用accept_mutex选项则此选项是指定如果另一个worker进程接受连接的最长时间。
3.multi_accept:如果禁用此选项则worker进程会一次接受一个连接,否则worker进程将接受所有新连接。
4.use:指定使用处理连接的方法。一般不指定有nginx自己选择。
5.worker_connections:一个worker进程所能够响应的最大请求数量。则设置此选项是还需要考虑worker_rlimit_nofile选项的限制。

网络连接

1.keepalive_disable:指定禁用那种浏览器使用keepalive功能。设置成msie6则在收到POST请求时时禁用,设置成safari则禁用OS x系统的Safari浏览器的保持功能。
2.keepalive_requests:在keepalive连接上所允许请求的最大资源数。
3.keepalive_timeout:设置keepalive连接的 超时时间。
4.tcp_nodelay:nginx不要缓存数据,而是一段一段的发送。当需要及时发送数据时就应该设置这个选项,这样发送一个小数据块信息时就不能立即得到返回值。
5.tcp_nopush:在一个数据包中发送所有头文件,而不是一个接一个的发送。
6.client_body_timeout:定义读取客户端请求报文body的超时时间。超时时间仅设置在两个连续读取操作之间的时间,而不是用于传输整个请求体。如果客户端在此时间内未发送任何内容,则会将408(请求超时)错误返回给客户端。
7.send_time:发送响应报文的超时时长。仅在两个连续的写操作之间设置,而不是用于传输整个响应。如果客户端在此时间内未收到任何内容,则连接关闭。
8.clent_header_timeout:定义读取客户端请求报文header的超时。 如果客户端在此时间内未传输整个头,则会向客户端返回408(请求超时)错误。
9.reset_timeout_connection:启用或禁用重置超时连接。 复位如下进行。 在关闭套接字之前,将对其设置SO_LINGER选项,其超时值为0.当套接字关闭时,TCP RST将发送到客户端,并释放此套接字占用的所有内存。 这有助于避免使已填充缓冲区的已关闭套接字长时间处于FIN_WAIT1状态。应注意,超时keep-alive 连接正常应该关闭。

内存和磁盘资源分配

1.client_body_buffer_size:设置用于读取客户端请求报文body的缓冲区大小。当请求报文body大于缓冲区大小整个整个主体部分写入到临时文件中。32位系统默认是8k,在64位系统中是16k。
2.client_body_in_file_only:指定是否将客户端的请求报文保存到文件中,该指令一般是在调试中使用。
3.clinet_body_in_single_buffer:指定是否将客户端的请求报文保存在单个缓冲区中。
4.client_body_temp_path:指定客户端请求报文的临时存放目录。目录可以使用三级子目录形式。
5.client_header_buffer_size:指定客户端请求报文的header的缓冲区大小。大多数情况下默认的1k已经足够使用,如果请求包括长cookie或者来自WAP客户端就需要进行调整。如果请求报文中不适合则由large_client_header_buffers指令进行配置缓冲区大小。
6.client_max_body_size:设置在客户端的请求报文的body中“Content-Length”字段的最大允许大小。如果请求大小超过此大小则会报413错误。设置为0将禁用对客户机请求正文大小的检查。
7.large_client_header_buffers:设定客户端请求报文header的缓冲区最大数量和大小。请求行不能超过一个缓冲区的大小,超过则会显示414(Request-URI Too Large)错误返回到客户端。 请求报文header字段也不能超过一个缓冲区的大小,超过则会显示400(Bad Request)错误返回到客户端。

文件传输

1.aio:启用或者禁用异步文件I/O。如果启用aio则还需要设置directio。
2.directio:读取大于或者等于指定大小的文件是允许使用directio方式传输。
3.sendfile:启用或者禁用sendfile()传输文件。
4.sendfile_max_chunk:当设置为非0时限制单个sendfile()调用中传输的数据量。
5.output_buffers:设置用于从磁盘读取响应报文的缓冲区数量和大小。

sendfile工作说明

在传统的文件传输read()、write()中其具体工作流程如下:调用read()把文件数据copy到内容缓冲区中-->read()将数据从内核缓冲区copy到用户缓冲区中-->write()将文件数据从用户的缓冲区中copy到内核与socket相关的缓冲区中-->文件数据从socket缓冲封装好报文响应并发送。

上面的流程可以简化成如下:
硬盘-->内核buf-->用户buf-->内核socket相关缓冲区-->协议引擎

而使用sendfile()进行传输则不会在把数据copy到用户空间,而是直接从内核缓冲区进行操作,具体工作流程如下:
sendfile()系统调用,文件数据copy到内核缓冲区-->数据从内核缓冲区到socket相关的缓冲区-->最后从socket相关的缓冲区copy到协议引擎

sendfile、aio使用说明

在使用AIO时需要设置directio选项,并且aio生效则sendfile就不会使用。在Linux中要么使用aio读取到缓冲区,要么用sendfile直接发送两者不可同时使用。
在配置directio时是针对每个请求文件大小而决定是否开启directio。例如我们设置成:directio 5m;。此选项说明如果文件小于5m则使用sendfile进行传输,而directio则会禁用从而aio也不会使用。如果传输的文件大于或者等于5m那么将启用directio,从而aio生效,而sendfile并不生效。
这种设计貌似刚好把linux下aio和sendfile两种机制的优点很好的结合起来使用。对于大文件采用aio,节省cpu,而对于小文件,采用sendfile,减少拷贝;并且对于大文件aio采用directio,避免挤占文件系统缓存,让文件系统缓存更多的小文件。 从理论上来看,这种配置比较适合系统内存有限、小文件请求比较多、间隔有几个大文件请求的Web环境;如果内存足够大,那么应该充分利用文件系统缓存,而directio使得aio无法使用缓存是衡量最终是否需要采用aio的一个需要仔细考虑的因素;

header过滤

1.ignore_invalid_headers:控制是否应忽略具有无效名称的header字段。 有效名称由英文字母,数字,连字符以及可能的下划线组成(由underscores_in_headers指令控制)。如果在服务器级别指定了伪指令,那么只有在服务器是默认值时才使用该值。 指定的值也适用于侦听相同地址和端口的所有虚拟服务器。
2.underscores_in_headers:启用或禁用在客户端请求报文header字段中使用下划线。 当禁用下划线的使用时,其名称包含下划线的请求标题字段将被标记为无效,并受到ignore_invalid_headers指令的约束。如果在服务器级别指定了伪指令,那么只有在服务器是默认值时才使用该值。 指定的值也适用于监听相同地址和端口的所有虚拟服务器。

HTTP头是可以包含英文字母([A-Za-z])、数字([0-9])、连接号(-)hyphens, 也可义是下划线(_)。在使用nginx的时候应该避免使用包含下划线的HTTP头。主要的原因有以下2点。
1.默认的情况下nginx引用header变量时不能使用带下划线的变量。要解决这样的问题只能单独配置underscores_in_headers on。
2.默认的情况下会忽略掉带下划线的变量。要解决这个需要配置ignore_invalid_headers off。

当然,nginx设置变量的时候是没有任何这样的限制的,可以直接设置带下划线的header。但是最好不要这样做。在使用nginx做多级代理的时候,也需要注意一些header不要重复设置。比如用来保存用户IP的这个header只在最上层的nginx里配置就行,后面的nginx不要重复设置导致覆盖。

安全

1.disable_symlinks:确定打开文件时应该如何处理符号链接。

  • off:路径名中的符号链接是允许的,不检查。这是默认行为。
  • on:如果路径名的任何组件是符号链接,则拒绝对文件的访问。
  • if_not_owner:如果路径名的任何组件是符号链接,并且链接指向的链接和对象具有不同的所有者,则拒绝对文件的访问。
  • from=part:当检查符号链接(参数on和if_not_owner)时,通常会检查路径名的所有组件。通过另外指定from = part参数可以避免检查路径名的初始部分中的符号链接。在这种情况下,只从指定的初始部分后面的路径名组件检查符号链接。如果值不是选中的路径名的初始部分,则将检查整个路径名,如同完全未指定此参数一样。如果值与整个文件名匹配,则不检查符号链接。参数值可以包含变量。

2.server_token:启用或禁用在错误消息和“Server”响应头字段中发出nginx版本。

https://segmentfault.com/a/1190000007897976
https://my.oschina.net/wmy596/blog/693898
http://www.cnblogs.com/leezhxing/p/4374035.html
http://pmghong.blog.51cto.com/3221425/1178836
https://github.com/qiwsir/ITArticles/blob/master/Nginx/配置性能优化的方法.md
https://www.zybuluo.com/ty4z2008/note/290139
http://www.z-dig.com/nginx-optimization-25.html
https://mos.meituan.com/library/30/how-to-optimize-nginx/

posted @ 2017-03-24 00:15  ProfiBus  阅读(1035)  评论(0编辑  收藏  举报