文章目录
  1. 1. 主要模块
    1. 1.1. location模块
    2. 1.2. Rewrite模块
      1. 1.2.1. if指令:
      2. 1.2.2. break指令
      3. 1.2.3. return指令
      4. 1.2.4. set指令
      5. 1.2.5. rewrite指令
      6. 1.2.6. rewrite_log指令
    3. 1.3. Proxy模块
    4. 1.4. upstream模块
    5. 1.5. 内置变量

主要模块

location模块

location是Nginx的重要模块,基本语法:location [=|~|~*|^~] /uri/ { … }

  1. “=” 严格匹配。如果这个查询匹配,那么将停止搜索并立即处理此请求
  2. “^~” 表示URI定位必须以指定模式开始,如果匹配,停止搜索其他模式
  3. “~” 和 “~*” 为区分大小写匹配和不区分大小写匹配
  4. “!~”和“!~*” 为区分大小写不匹配和不区分大小不匹配
  5. “@xxx” 表示定义location区段名,客户端不能访问,内部产生的请求可以,例如try_files或error_page
  6. “/” 表示通用匹配,任何请求都会匹配到
    如果多个location匹配按什么顺序呢?Nginx首先会按“=”去匹配,匹配不了然后按照“^~”匹配,如果还是匹配不了,就会按location的顺序匹配其他的规则,最后还是没匹配就使用“/”通用匹配。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#精确匹配,不能用正则
location = /abc {
}

#URI定位匹配,可用正则
location ^~ /abc {
}

#正则匹配 区分大小写
location ~ /abc {
}

#正则匹配 不区分大小写
location ~* /abc {
}

#匹配所有
location / {

}

Rewrite模块

Nginx Rewrite模块作用:为了URL重定向,过滤危险的URL;相关指令包括if,rewrite,set,return,break等,其中最关键的就是rewrite。

if指令:

语法:if(condition){}
默认值:无
作用域:server,location
用于检查一个条件是否符合,如果条件符合,就执行大括号中的内容;if指令不支持嵌套,不支持多个条件的&&和||处理。
a.表达式为一个变量时,如果值为空或者任何以0开头的字符串都会当作false;
b.直接比较内容时,可以使用 = 和 !=;
c.正则表达式匹配时,可以使用“~”和“~*”,分别表示区分大小写匹配和不区分大小写匹配
d.可以使用“-f”和“!-f”来判断文件是否存在,使用“-d”和“!-d”判断目录是否存在,使用“-e”和“!-e”判断文件或者目录是否存在,使用“-e”和“!-e”判断文件是否可执行;
e.部分正则表达式在”()”中的匹配值可以通过$1至$9访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#如果UA包含”MSIE”,rewrite 请求到/msie目录下
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}

#如果cookie匹配正则,设置变量$id等于正则引用部分
if ($http_cookie ~* "id=([^;] +)(?:;|$)" ) {
set $id $1;
}

#如果提交方法为POST,则返回状态405
if ($request_method = POST ) {
return 405;
}

#如果请求的文件不存在
if(!-f $request_file_name){
break;
proxy_pass http://127.0.0.1
}

#如果query string中包含”post=140″,永久重定向到example.com
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
}

break指令

语法:break;
默认值:无
作用域:server,location,if
停止执行当前虚拟主机的后续rewrite指令集

1
2
3
4
if ($slow) {
limit_rate 10k;
break;
}

return指令

语法:return code,return code URL,return URL;
默认值:无
作用域:server,location,if
停止处理并返回指定状态码(code)给客户端。非标准状态码444表示关闭连接且不给客户端发响应头。从0.8.42版本起,return支持响应URL重定向(对于301,302,303,307),或者文本响应(对于其他状态码).对于文本或者URL重定向可以包含变量。

set指令

语法:set variable value;
默认值:none
作用域:server,location,if
定义一个变量并赋值,值可以是文本,变量或者文本变量混合体。

rewrite指令

语法:rewrite regex replacement [flag];
默认值:无
作用域:server,location,if
如果一个URI匹配指定的正则表达式regex,URI就按照replacement重写;rewrite按配置文件中出现的顺序执行。flags标志可以停止继续处理;如果replacement以”http://"或"https://"开始,将不再继续处理,这个重定向将返回给客户端。
falg参数:

  • last 停止处理后续rewrite指令集,然后对当前重写的新URI在rewrite指令集上重新查找;
  • break 停止处理后续rewrite指令集,并不在重新查找,但是当前location内剩余非rewrite语句和location外的的非rewrite语句可以执行。
  • redirect 如果replacement不是以http://或https://开始,返回302临时重定向,一般用于重定向到完整的URL(包含http[s]:部分) ,地址栏会改变.
  • permanent 返回301永久重定向,地址栏会改变。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    if (-f $uri) {
    break
    }
    if ($uri ~ ^/admin/){
    return 403;
    }
    #URL重写,如 /search/nginx-->/search.php?q=nginx
    if ($uri ~ ^/search/(.*)$) {
    set $query $1;
    rewrite ^ /search.php?q=$query?;
    }

注意:
1.rewrite只对相对路径进行匹配,不包含hostname;
2.正则表达regex式中包含 “}” 或 “;”, 那么整个表达式需要用双引号或单引号包围.
3.rewrite的正则是不匹配querystring的,所以默认情况下,querystring是自动追加到rewrite后的地址上的,如果不想自动追加query string,则在rewrite地址的末尾添加?

1
rewrite ^/users/(.*)$ /show?user=$1? last;

rewrite_log指令

语法:rewrite_log on|off;
默认值:rewrite_log off;
作用域:http,server,location,if
开启或关闭以notice级别打印rewrite处理日志到error log文件。

1
2
rewrite_log on;
error_log logs/xxx.error.log notice;

Proxy模块

此模块的作用:将客户端的HTTP请求转到后端服务器,从而实现反向代理

1
2
3
4
5
6
7
8
9
10
11
location / {
proxy_pass http://localhost:8080; #设置代理服务器的端口,套接字或者url
proxy_pass_header Server; #该指令强制一些被忽略的头传递到客户端
proxy_redirect off; #允许改写出现在HTTP头却被后端服务器触发重定向的URL,对相应本身不做任何处理
proxy_set_header Host $http_host; #允许你重新定义代理header值再转到后端服务器.目标服务器可以看到客户端的原始主机名
proxy_set_header X-Real-IP $remote_addr; #目标服务器可以看到客户端的真实ip,而不是转发服务器的ip
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 600; #跟后端服务器连接的超时时间,发起握手等候响应超时时间
proxy_read_timeout 600; #连接成功,等候后端服务器的响应时间_其实已经进入后端的排队中等候处理。默认值:
proxy_send_timeout 600; #后端服务器回传时间_就是在规定时间内后端服务器必须传完所有的数据。设置代理服务器转发请求的超时时间,同样指完成两次握手后的时间,如果超过这个时间代理服务器没有数据转发到后端服务器,nginx将关闭连接。
}

upstream模块

Nginx的upstream目前支持5种方式的分配:

  1. 轮询(默认)
    每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

    1
    2
    3
    4
    upstream my {
    server 192.168.0.1:8000;
    server 192.168.0.1:8001;
    }
  2. 权重 weight
    指定权重,weight和访问比率成正比,用于后端服务器性能不均的情况。

    1
    2
    3
    4
    upstream my {
    server 192.168.0.100 weight=4;
    server 192.168.0.101 weight=8;
    }
  3. ip_hash
    每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以
    解决session不同步的问题。

    1
    2
    3
    4
    5
    upstream my {
    ip_hash;
    server 192.168.0.100:80;
    server 192.168.0.101:80;
    }
  4. fair(第三方)
    按后端服务器的响应时间来分配请求,响应时间短的优先分配。需要安装Upstream Fair Balancer Module。

    1
    2
    3
    4
    5
    upstream my {
    server 192.168.0.100:80;
    server 192.168.0.101:80;
    fair;
    }
  5. url_hash(第三方)
    按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务
    器为缓存时比较有效。需要安装Upstream Hash Module.

    1
    2
    3
    4
    5
    upstream my {
    server 192.168.0.100:80;
    server 192.168.0.101:80;
    hash $request_uri;
    }

每个server都可以配置自己的状态:
down: 表示此服务器不参与负载;
weight:表示权重,默认值为1,权重越大,表示负载越大,一般根据服务器的性能分配;
max_fails: 表示请求的最大失败次数,默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误;
fail_timeout: 表示max_fails次失败后,暂停的时间;
backup: 表示当其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

问题1:nginx如何判断节点为失效状态?
答:Nginx 默认判断失败节点状态以connect refuse和time out状态为准,不以HTTP错误状态进行判断失败,因为HTTP只要能返回状态说明该节点还可以正常连接,所以nginx判断其还是存活状态,除非添加了proxy_next_upstream指令设置对404、502、503、504、500和time out等错误进行转到备机处理,在next_upstream过程中,会对fails进行累加,如果备用机处理还是错误则直接返回错误信息(但404不进行记录到错误数,如果不配置错误状态也不对其进行错误状态记录),综述,nginx记录错误数量只记录timeout 、connect refuse、502、500、503、504这6种状态,timeout和connect refuse是永远被记录错误状态,而502、500、503、504只有在配置proxy_next_upstream后nginx才会记录这4种HTTP错误到fails中,当fails大于等于max_fails时,则该节点失效。
问题2:nginx 处理节点失效和恢复的触发条件是什么?
答:nginx可以通过设置max_fails(最大尝试失败次数)和fail_timeout(失效时间,在到达最大尝试失败次数后,在fail_timeout的时间范围内节点被置为失效,除非所有节点都失效,否则该时间内,节点不进行恢复)对节点失败的尝试次数和失效时间进行设置,当超过最大尝试次数或失效时间未超过配置失效时间,则nginx会对节点状会置为失效状态,nginx不对该后端进行连接,直到超过失效时间或者所有节点都失效后,该节点重新置为有效,重新探测
问题3:所有节点失效后nginx做什么?
答:如果探测所有节点均失效,备机也为失效时,那么nginx会对所有节点恢复为有效,重新尝试探测有效节点,如果探测到有效节点则返回正确节点内容,如果还是全部错误,那么继续探测下去,当没有正确信息时,节点失效时默认返回状态为502,但是下次访问节点时会继续探测正确节点,直到找到正确的为止。

内置变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$arg_PARAMETER   #这个变量包含在查询字符串时GET请求PARAMETER的值。
$args #这个变量等于请求行中的参数。
$binary_remote_addr #二进制码形式的客户端地址。
$body_bytes_sent #传送页面的字节数
$content_length #请求头中的Content-length字段。
$content_type #请求头中的Content-Type字段。
$cookie_COOKIE #cookie COOKIE的值。
$document_root #当前请求在root指令中指定的值。
$document_uri #与$uri相同。
$host #请求中的主机头(Host)字段,如果请求中的主机头不可用或者空,则为处理请求的server名称(处理请求的server
#的server_name指令的值)。值为小写,不包含端口
$hostname #机器名使用 gethostname系统调用的值
$http_HEADER #HTTP请求头中的内容,HEADER为HTTP请求中的内容转为小写,-变为_(破折号变为下划线),
#例如:$http_user_agent(Uaer-Agent的值), $http_referer...
$sent_http_HEADER #HTTP响应头中的内容,HEADER为HTTP响应中的内容转为小写,-变为_(破折号变为下划线),
#例如: $sent_http_cache_control, $sent_http_content_type...;
$is_args #如果$args设置,值为"?",否则为""。
$limit_rate #这个变量可以限制连接速率。
$nginx_version #当前运行的nginx版本号。
$query_string #与$args相同。
$remote_addr #客户端的IP地址。
$remote_port #客户端的端口。
$remote_user #已经经过Auth Basic Module验证的用户名。
$request_filename #当前连接请求的文件路径,由root或alias指令与URI请求生成。
$request_body #这个变量(0.7.58+)包含请求的主要信息。在使用proxy_pass或fastcgi_pass指令的location中比较有意义。
$request_body_file #客户端请求主体信息的临时文件名。
$request_completion #请求完成
$request_method #这个变量是客户端请求的动作,通常为GET或POST。包括0.8.20及之前的版本中,这个变量总为mainrequest中的动作,如果当前请求是一个子请求,并不使用这个当前请求的动作。
$request_uri #这个变量等于包含一些客户端请求参数的原始URI,它无法修改,请查看$uri更改或重写URI。
$schemeHTTP #方法(如http,https)。按需使用,例:
rewrite ^(.+)$ $scheme://example.com$1 redirect;
$server_addr 服务器地址,在完成一次系统调用后可以确定这个值,如果要绕开系统调用,则必须在listen中指定地址并且使用bind参数。
$server_name #服务器名称。
$server_port #请求到达服务器的端口号。
$server_protocol #请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$uri #请求中的当前URI(不带请求参数,参数位于$args),可以不同于浏览器传递的$request_uri的值,它可以通过内部重定向,或者使用index指令进行修改。

参考:
[1] http://www.nginx.cn/216.html
[2] http://blog.cafeneko.info/2010/10/nginx_rewrite_note/
[3] http://saiyaren.iteye.com/blog/1914865

文章目录
  1. 1. 主要模块
    1. 1.1. location模块
    2. 1.2. Rewrite模块
      1. 1.2.1. if指令:
      2. 1.2.2. break指令
      3. 1.2.3. return指令
      4. 1.2.4. set指令
      5. 1.2.5. rewrite指令
      6. 1.2.6. rewrite_log指令
    3. 1.3. Proxy模块
    4. 1.4. upstream模块
    5. 1.5. 内置变量