详见官网(搜关键词location):http://nginx.org/en/docs/http/request_processing.html
(1)假设所有server { } 均listen 端口 * : 80,在形如以下这种配置,nginx仅根据请求header中的“Host”字段来进行路由选择对应的虚拟server。如果没有匹配到任何server_name或者请求header中没有“Host”字段,则nginx匹配此端口对应的默认虚拟server。在这里就是排在第一位的虚拟server,这也是nginx标准的默认server选择方式;但也可以指定默认server,0.8.21以上版本形如listen 80 default_server,早期版本中形如listen 80 default。
特别的,指定默认server是监听端口的属性,而不是server_name的属性。
server {
listen 80;
server_name example.org www.example.org;
...
}
(2)假设所有server{ } 均listen具体的 ip:port,在形如以下这种配置,nginx会对照server块中的listen配置,先测试请求的IP/Port,然后在匹配到的server块中再接着测试请求header中的“Host”字段,若在该server块中没有server_name匹配此“Host”,则请求会被相应的默认server所处理。由于default是listen的属性,因此不同的ip:port可以分别指定为相应的默认server。
server {
listen 192.168.1.1:80;
server_name example.org www.example.org;
...
}
(3)阻止没有“host”字段的请求,server可以直接丢弃这类请求,按以下方式配置。非标准码444意为关闭连接,0.8.48以上版本中 server_name的默认设置就是"",因此这里可以省略不写"",而在早期版本中默认的server_name是主机的hostname。
server{
listen 80;
server_name "";
return 444;
}
详见官网(搜关键词location):http://nginx.org/en/docs/http/request_processing.html
网上半桶水货的讹传太多,官网才是权威的来源。。。
(1)首先搜索最长匹配的文字字符串规则(即非正则表达式规则),不管这些常规的文字字符串规则是按照什么顺序先后出现的,即这些常规文字字符串规则出现的先后顺序不影响nginx匹配文字字符串规则的结果。
(2)其次搜索匹配的正则表达式规则,按照正则表达式规则出现的先后顺序进行匹配,一旦匹配上则停止继续搜索正则表达式规则,并执行该正则表达式所对应的location块。
(3)最后若没有搜索到匹配的正则表达式规则,则使用在(1)中搜索到的最长匹配的文字字符串规则。
特别的:location / { }可以匹配所有的请求,因此其在最长文字字符串匹配规则中的优先级也是最低的,location规则仅匹配请求行中的URI段而不匹配请求参数。
当请求是 / 时,只会被匹配到location / {index xxx yyy},此时index指令会先后测试这些指定的index files,假设index指令形如index index.html index.php;若index.html不存在而index.php存在,则nginx会重新发起一个内部重定向,重新进行location匹配,就好像这个请求是从客户端发起的。
另外,目前location的正则匹配规则中没有取“非”语法。
nginx配置文件采用树形结构组织,使用一系列的括弧({ })嵌套来定义层次结构,在nginx中这些括弧所定义的区域被称为“contex”。由于一个context可以被另一个context所包含,nginx提供了指令的继承级别:如果一个指令在多个嵌套的区域内有效,那么在更宽泛的context下所定义的指令将会被传递到child contexts并作为其默认值;child contexts也可以随意覆盖这些值。
main context(global context):位于任一context之外,它表述了nginx配置最宽泛的环境,定义了最基础的影响整个程序的细节,很多指令不能被低层的context继承。可定义user、worker_processes、worker_cpu_affinity、worker_rlimit_nofile、error_log、pid等普通细节。
events context:位于main context内,nginx使用event-based的连接处理模型,它设置了nginx如何处理连接。
http context:包含指令以及其它context,定义了如何处理http或https连接。
sever context:允许重复定义,每个实例定义一个特定的虚拟server用于处理客户端的请求,nginx根据listen和server_name来选择使用哪个虚拟server来响应一个请求。在这个context里可以定义指令覆盖http context中定义的很多指令。
location context:位于 sever context。
other context:比如split_clients、perl 、map、geo、types、charset_map。
upstream context:配置了"upstream" servers,定义了一个server池可供nginx发送代理请求。
if context:类似传统程序中的if声明,在if context中return和rewrite指令被认为是可靠安全的。
最后建议少用if context而是多用其它sibling context:(1)if context未经过大量测试;(2)nginx已优化用于选择server context和location context的算法。
原文详见:
https://www.digitalocean.com/community/tutorials/understanding-the-nginx-configuration-file-structure-and-configuration-contexts
指令proxy_set_header比较特殊:nginx允许重新定义或增加传递给proxied server的header域字段,字段的值可以是文本、变量或二者的组合。当且仅当当前context level 没有设置任何proxy_set_header指令,当前context level才会从前面的context level继承proxy_set_header指令;这就意味着若当前context level存在proxy_set_header指令则上一个context level的任一proxy_set_header指令均不会被继承(即对当前context level无效)。
可以增加其它header字段或cookie字段,增加cookie字段的指令类似如下:
proxy_set_header Cookie "$http_cookie; cookie _name_xx=value_yy";
当nginx反向代理一个请求时会自动调整从客户端收到的header信息:
(1)丢弃任何值为空的header字段;
(2) 名称带有下划线的header字段被视为非法并丢弃,除非underscores_in_headerson;
(3)”Host” 字段值会被重写为 $proxy_host(upstream ip/name和port);
(4)”Connection”字段值被设置为”close”,即告诉upstreamserver一旦nginx响应了原始请求即关闭和upstream server的连接,upstream server不可认为此连接是长连接。
原文详见:
https://www.digitalocean.com/community/tutorials/understanding-nginx-http-proxying-load-balancing-buffering-and-caching
Syntax: rewrite regex
replacement
[flag];
Default: —
Context: server
, location
, if
Flag: break, last, redirect, permanent
rewrite使用PCRE正则表达式来改变请求的URI,rewrite指令的执行方式如下:
(1) 位于server level(server context) 的rewrite指令按先后顺序执行;
(2) 重复地:
<1> 基于请求URI匹配location;
<2> 在匹配的location中按先后顺序执行rewrite指令;
<3> 如果URI被 rewritten,循环执行该过程,但最多不超过10次。
break: 终止rewrite模块当前指令集合的执行,如果break是在location中,那么该location中的其它非rewrite指令将继续执行。
last: 终止rewrite模块当前指令集合的执行,发起一个内部重定向,重新搜索进行location匹配。
redirect: 返回302临时重定向,当替换后的URI(replacement
)不是以“http”或“https”开头时使用。
permanent: 返回301永久重定向。
如果replacement
中包含新的请求参数,那么之前请求的参数将追加在新的参数后,如果不希望之前的参数被追加,那么紧接着replacement放置一个“?”即可。 形如:
rewrite^/users/(.*)$ /show?user=$1? last;
如果rewrite正则表达式中包含 ”}” 或 “;” ,那么整个正则表达式应该被单引号或双引号所包围。$request_uri表示请求的URI。
return指令: 停止处理并返回指定的状态码,非标准状态码444关闭一个连接且不发送响应头。return语法如下,当URL作为唯一的参数且以“http”、“https”、“$scheme”开头时发送的状态码是302。
return code [text];
return code URL;
return URL;
测试break的方式如下:各testx.php 打印自身文件名。
case 1:
if ( $request_uri = "/test.php" ){
rewrite ^/.* /test1.php break;
}
rewrite ^/.* /test2.php break;
location ~ ^/test { #此location context中无rewrite指令
……
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
……
}
测试表明:打印的结果“test1”,即“rewrite^/.* /test2.php break;”不会被执行,而搜索匹配location正则仍然继续执行,也即只是servercontext的rewrite模块执行被终止了。
case2:在case1的locationcontext中增加指令:“rewrite ^/.* /test3.phpbreak;”,
打印的结果是“test3”。
case3:在case1的基础上增加一个location,其它保持不变。
location ~ ^/test1 {
rewrite ^/.* /test3.php last;
……
}
打印的结果是“test3”,测试表明 “rewrite ^/.* /test2.php break;”没有被执行。
综上可知:(1)server context中的“rewrite regex
replacement
break
”
一旦执行将会使得server context中的其它任何rewrite都不会被执行;(2)location context中的“rewrite regex
replacement
last
”
被执行后不会再去搜索匹配server context中的rewrite指令,而只会去搜索匹配location context。
(1)listen address[:port] [backlog=number],参数backlog 限制了用于存放处于挂起状态连接的队列最大长度, 已连接但未进行accept处理的SOCKET队列大小,即这些连接已经完全建立了,但还没有被处理,其默认值是 -1。当一个连接请求到达时,如果此时队列满了,客户端会收到连接拒绝(“Connection refused”)。
php-fpm的backlog大小设置跟php-fpm的处理能力有关,backlog太大了,导致php-fpm处理不过来,nginx那边等待超时,断开连接,报504 gateway timeout错。同时php-fpm处理完准备write 数据给nginx时,发现TCP连接断开了,报“Broken pipe”。 php-fpm的backlog太小的话,nginx之类的client请求,根本进入不了php-fpm的accept queue,报“502 Bad Gateway”错。所以,这还得去根据php-fpm的QPS来决定backlog的大小。计算方式最好为QPS=backlog。
详见:http://nginx.org/en/docs/http/ngx_http_core_module.html
相关:http://www.cnxct.com/something-about-phpfpm-s-backlog/
http://mp.weixin.qq.com/s?__biz=MjM5NzUwNDA5MA==&mid=201005717&idx=1&sn=74036633114ee6212e57ee4576dbfcbc&3rd=MzA3MDU4NTYzMw==&scene=6#rd
(2)以下是一个静态集群中的配置:当访问一个文件失败时可进行rewrite,这样其它location就可以可处理了,这里用到了try_files 语法。
七、配置实例
以下示例中每个servercontext 可以分别存放在不同的文件中,并使用include将其包含在主配置文件的末尾即可,形如 include vhost/v1.conf;include vhost/v2.conf;还可以将rewirte规则用lua语法写在文件中,然后使用rewrite_by_lua_file包含相应的lua文件即可。
#user nobody;
worker_processes 8;
worker_cpu_affinity 00000001 0000001000000100 00001000 00010000 00100000 01000000 10000000;
worker_rlimit_nofile 204800;
#error_log logs/error_log debug;
error_log /home/log/error_log notice;
pid /home /var/nginx.pid;
events {
use epoll;
worker_connections 204800;
}
http {
include mime.types;
include upstream.conf;
default_type application/octet-stream;
ignore_invalid_headers off;
server_names_hash_bucket_size 128;
client_header_buffer_size 4k;
large_client_header_buffers 4 32k;
client_max_body_size 3m;
client_body_buffer_size 8k;
client_body_timeout 15;
client_header_timeout 10;
send_timeout 240;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
fastcgi_connect_timeout 5;
fastcgi_send_timeout 10;
fastcgi_read_timeout 10;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
fastcgi_intercept_errors on;
keepalive_timeout 0;
#keepalive_timeout 65;
gzip on;
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;
gzip_vary on;
#problem_tracing off;
log_format main '$remote_addr - $remote_user [$time_local]"$request" '
'$status $body_bytes_sent "$http_referer""$http_cookie" "$http_user_agent" '
'$request_time $http_x_logid $http_x_routerip$server_addr $upstream_addr $host '
'"$http_x_forwarded_for" ';
server {
listen 8080;
server_name xx.com yy.com;
more_set_headers 'Server: Nginx;
error_page 400 403 404 500 501 502 503 504 505 http://uu.com/ error.html;
set_real_ip_from 192.0.0.0/8;
real_ip_header X-Real-IP;
access_log /home/log/access_log main;
location / {
root /home/app/site;
rewrite ^/aa/v1/(.*)$ /ee/index.php last;
rewrite ^/test/(.*)$ /test/$1 break;
rewrite ^/bb.icon$ /img/bb.icon break;
rewrite ^/.* /default/index.php last;
}
location ~ ^/(ee|default)/index.php$ {
root /home/app/web;
fastcgi_pass unix:/home/php/var/php-cgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_split_path_info^(.+\.php)(.*)$;
fastcgi_param PATH_INFO$fastcgi_path_info;
fastcgi_param LOGID $logid;
include fastcgi_params;
}
}
server {
listen 8080;
server_name ww.com zz.com;
more_set_headers 'Server: Nginx;
error_page 400 403 404 500 501 502 503 504 505 http://uu.com/error.html;
set_real_ip_from 192.0.0.0/8;
real_ip_header X-Real-IP;
access_log /home/log/access_log main;
location ~ ^/(js |img|css)/ {
root /home/app/static;
expires 30d;
}
}
}