nginx基础配置篇
Posted 那个天真的人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nginx基础配置篇相关的知识,希望对你有一定的参考价值。
序言
nginx是非常流行的一个http反向代理服务器,虽然不是专业的运营人员,但作为开发人员,掌握一些基本的用法也是蛮必要的,本篇记录nginx的一些基本配置。
调整工作进程数
nginx启动会创建主进程和工作进程,默认只会创建一个工作进程用于处理连接(底层使用epoll等事件处理模型),如果是多核服务器,建议把工作进程的数量设置为cpu的核数,如8核cpu可以如下设置:
worker_processes 8;
基本资源访问
1) 最常见的nginx用法就是把它当作一个静态资源服务器,先看一个最简单的例子:
在本机hosts文件中如下配置: 127.0.0.1 static.test.com
nginx.conf配置server:
server
listen static.test.com;
root D:/learn/static;
然后访问 http://static.test.com/hello.js 即可以访问到 D:/learn/static/hello.js。
2) 我们也可以配置多个域名同时访问同一个资源
在hosts中添加如下映射:127.0.0.1 static2.test.com
nginx.conf配置server:
server
listen 80;
server_name static.test.com static2.test.com;
root D:/learn/static;
访问http://static2.test.com/hello.js 即可以访问到 D:/learn/static/hello.js。
3) 此外,域名还可以使用通配符,比如,所有以 test.com结尾的域名都支持访问hello.js,
修改nginx.conf,如下:
server
listen 80;
server_name *.test.com;
root D:/learn/static;
此时 http://static2.test.com/hello.js 仍然是有效的。
4) 也可以使用正则对域名进行匹配
修改nginx.conf,如下:
server
listen 80;
server_name ~^(.+)\\.test\\.com$;
root D:/learn/$1;
此时访问 http://static.test.com/hello.js 相当于访问 D:\\learn\\static\\hello.js
此时访问 http://static2.test.com/hello.js 相当于访问 D:\\learn\\static2\\hello.js
可以实现多站点动态目录。
5) 简单的location
有时候我们需要定义访问的一些路径,可以简单使用 location,如下所示:
server
listen 80;
server_name static.test.com;
location /static
root D:/learn/;
访问 http://static.test.com/static/hello.js,实际上会转成 D:/learn/static/hello.js
6) 可以使用别名来实现5的功能
配置如下:
server
listen 80;
server_name static.test.com;
location /static
alias D:/learn/static;
访问 http://static.test.com/static/hello.js,实际上会转成 D:/learn/static/hello.js,可以认为别名是一种替换,使用 D:/learn/static 来替换 /static。
强大的location
location的功能比较强大,规则比较多,但只要总结好,还是不难记住的。
location主要配置两种路径格式:普通格式 和 正则表达式,一般在server下面都会配置多个location,这时候,如何匹配就显示尤为关键了。先来看下location的语法格式:
location [=|~|~*|^~|@] /uri/ …
可以看到一共支持5种前缀,再加上可以没有前缀,所以一共有6种格式。前面说过,分大类的话,其实只有两类:
普通格式 (4种) | 正则(2种) |
---|---|
= 精确匹配 ^~ 不需要继续正则匹配 @ 命名 location (没有前缀也算一种) | ~ 区分大小写 ~* 不区分大小写 |
nginx在匹配的时候,会把server下面的location分为普通格式组和正则组,先匹配普通组,如果有必要,再匹配正则组。
接下来简要描述匹配的大致算法流程:
1、分组,根据6种前缀,先分为普通格式组 和 正则组;
2、 先匹配普通格式组;
a. 如果请求的路径跟location配置的路径完全一样,并且配置时有 = 前缀,命中此location,结束流程。
比如配置 location = /static/index.html ,访问 http://xx/static/index.html
这也就是精确匹配的由来。
b. 到这一步,=前缀就不再参与计算了,因为已经不可能精确匹配了。接着,在剩余的普通格式中,找出最长匹配请求路径的那一条location配置,如果这个location有 ^~前缀,那么命中此 location,结束流程,否则把这个location当作一个备胎先记住,然后执行正则组的匹配。
最长路径匹配说明:
location = /static/pathb/pathc/
location = /static/patha/
location = /static/
当访问 http://xx/static/patha/a.html 时,显然 location = /static/patha/ 这条路径匹配最长。
3、匹配正则组
说明: 正则组按照location出现的位置依次匹配,只要匹配上一个即刻终止。
前面说过,在普通组的匹配中,在某些情况下会有一个备胎location。当所有正则组都无法匹配到时,这个备胎就是最终匹配到的location,但是当任何一个正则匹配上的时候,就会使用此正则location,结束流程,备胎location将被丢弃。
举个简单的示例:
配置如下:
server
listen 80;
server_name static.test.com;
location /static/
deny all;
location ^~ /static/path/
allow all;
location ~ \\.html
deny all;
访问 http://static.test.com/static/path/index.html 时返回 404。
按照前面的算法流程,location ^~ /static/path/ 为普通格式中的最长匹配,而且还带有 ^~前缀,于是命中,匹配结束,由于我们没有配置映射的方式,所以找不到,返回了404。
细心的朋友可能发现没有说到@前缀,其实它主要用于其他用途。
比如有如下配置:
server
listen 80;
server_name static.test.com;
location ^~ /static/path/
allow all;
error_page 404 = @baidu;
location @baidu
proxy_pass http://www.baidu.com;
当访问 static.test.com/static/path/s?wd=nginx 的时候,虽然匹配上了location ^~ /static/path/ ,但结果却是404,这时候被error_page捕获到了,从而在nginx流转到了location @baidu,然后通过proxy_pass把请求转发给了http://www.baidu.com,经测试发现,浏览器重定向到了http://static.test.com/s?wd=nginx&tn=SE_PSStatistics_p1d9m0nf,然后确实可以显示百度返回的内容。
强大的rewrite模块
跟location一样,rewrite也是nginx中非常核心的特性,用于处理各种请求转发。一般提到rewrite,都会涉及到几个相关的指令,如下表所示:
指令 | 出现上下文 | 说明 |
---|---|---|
break | server,location,if | 完成当前的规则集,不再处理rewrite指令 |
if | server,location | 条件判断,不支持嵌套,不支持多个条件&&和 |
set | server,location,if | 用于定义一个变量,并给变量赋值。变量的值可以为文本、变量以及文本变量的联合。 |
return | server,location,if | 该指令用于结束规则的执行并返回状态码给客户端 |
rewrite | server,location,if | 该指令根据表达式来重定向URI,或者修改字符串。指令根据配置文件中的顺序来执行。注意重写表达式只对相对路径有效。语法: rewrite regex replacement flag |
有几个用于判断文件及目录匹配的,如下表所示:
指令 | 说明 |
---|---|
-f和!-f | 用来判断是否存在文件 |
-d和!-d | 用来判断是否存在目录 |
-e和!-e | 用来判断是否存在文件或目录 |
-x和!-x | 用来判断文件是否可执行 |
rewrite指令的最后一项参数为flag标记,flag标记有:
rewrite的flag标记 | 说明 |
---|---|
last | 如果一个location中有多个rewrite,表示停止本location后面rewrite的匹配,继续新一轮location匹配 |
break | 本条规则匹配完成后,终止匹配,整个匹配流程结束 |
redirect | 302临时重定向 |
permanent | 301永久重定向 |
学习rewrite相关的内容最简单就是通过示例来说明:
示例1:
server
listen 80;
server_name static.test.com;
if ($request_uri ~ /static/my)
rewrite ^/static/my/(.*)$ /static2/my/$1;
location /static2/my
root D:/resource/;
rewrite ^/static2/my/(.*)/(.*)$ /static3/my/$2.$1 break;
访问:http://static.test.com/static/my/txt/a 结果访问的是: D:/resource/static3/my/a.txt
解析:
首先,请求路径/static/my/txt/a 匹配上了if指令,所以被rewrite成了/static2/my/txt/a,接着,执行location匹配,匹配上了 location /static2/my,再次被rewrite成了/static3/my/a.txt,由于最后有break标识,终止整个流程,再结合root D:/resource/配置,最终就找到了 D:/resource/static3/my/a.txt。
示例2:
server
listen 80;
server_name static.test.com;
if ($request_uri ~ /static/my)
rewrite ^/static/my/(.*)$ /static2/my/$1;
location /static2/my
rewrite ^/static2/my/(.*)/(.*)$ /static3/my/$2.$1 break;
location /static3
root D:/resource/;
访问:http://static.test.com/static/my/txt/a ,结果返回了 404。
解析:
本示例跟示例1差不多,不同的就是 location /static2/my 中的 root被单独抽取出来了,结果就访问不了啦,说明,location中,如果匹配的rewrite以break为标识,要定义好路径映射。如果把location /static2/my 中的rewrite标识改为last,则又可以访问了,原因在于nginx的执行流程,步骤大致如下:
a. 先执行一次 server中的各类指令(过滤location)
b. 得到目前的路径(可能被rewrite过了),匹配location(前面部分已经详细说明过匹配规则),匹配location中的rewrite,当匹配上的rewrite以break结尾时,命中,结束整个流程;如果匹配上的rewrite以last结尾,那么中断当前location匹配,重新执行步骤b,一直到最大上限次数10次为止。(如果匹配上的location没有rewrite,那么提前中断,就像上面的 location /static3一样,直接就可以找到资源了)
示例3:
server
listen 80;
server_name static.test.com;
if ($request_uri ~ /static/my)
rewrite ^/static/my/(.*)$ /static4/my/$1;
rewrite ^/static4/my/(.*)$ /static2/my/$1;
location /static2/my
root D:/resource/;
rewrite ^/static2/my/(.*)/(.*)$ /static3/my/$2.$1 break;
访问:http://static.test.com/static/my/txt/a 结果访问的是: D:/resource/static3/my/a.txt
注意,在 if 提令中的rewrite并没有任何的flag,所以rewrite ^/static4/my/(.*)
/static2/my/
1;才能够执行,反之则不会执行,也就得不到我们想要的结果。
小小总结:
a. server上下文中,非location中的指令会先执行, 这时候注意rewrite的flag,如果为last或者break,那么会中断其他非locatoin中的rewrite配置执行
b. 当执行完非location中的指令,接着匹配location,如果匹配到的location中命中了rewrite,这时候,如果命中的rewrite以break结尾,则整个匹配流程结束,如果以last结尾,则要重新匹配location,最大执行10次(为避免死循环),所以要注意last和break的使用场景。
防盗链
有时候,我们要使用图片防盗链功能,nginx提供了简单便捷的防盗链使用方式。
图片防盗链主要是利用http referer头进行判断,这种方式是阻止不了写代码抓取图片的,但一般我们主要是防止图片被他人直接内嵌在网页中。
一个简单的配置如下:
server
listen 80;
server_name static.test.com;
valid_referers none blocked *.test.com ~.*\\.test2\\.com;
if ($invalid_referer)
return 403;
location /
root D:/resource/;
直接在浏览器访问:http://static.test3.com/fbb.jpg 是可以访问的,因为这时候没有referer头,符合none配置。
写个简单的html,包括如下内容:
<img src=”http://static.test3.com/fbb.jpg” />
访问html页面,发现图片无法出来,被403了。
把img内容改为 <img src=”http://static.test2.com/fbb.jpg” />这时候就可以正常访问了。
当referer验证不合法的时候,内置变量 $invalid_referer为1,所以会返回 403。
反向代理
反向代理使用proxy_pass指令来实现,也是非常好用的功能。出现上下文: http、server、location。
先来研究下最简单的proxy_pass使用:
示例1:
proxy_pass为单纯的域名,并且后缀没有带 /
server
listen 80;
server_name static.test.com;
location /web/
proxy_pass http://static.test2.com;
server
listen 80;
server_name static.test2.com;
location /
root D:/resource/;
访问http://static.test.com/web/test.html 是正常的。
提取路径: /web/test.html,直接添加到 proxy_pass后面,就是最终访问路径。
示例2:
proxy_pass为单纯的域名,并且后缀带了/
server
listen 80;
server_name static.test.com;
location /web/
proxy_pass http://static.test2.com/;
server
listen 80;
server_name static.test2.com;
location /
root D:/resource/web;
以上配置同样可以访问: http://static.test.com/web/test.html。
当proxy_pass带了/的时候,解析如下 :
提取路径: /web/test.html,去掉 /web/, 得到 test.html,跟proxy_pass拼在一起,得到
http://static.test2.com/test.html。
示例3:
proxy_pass除了域名,还带了路径,这种情况下,不管路径后面有没有/,都使用跟示例2一样的规则,配置如下:
server
listen 80;
server_name static.test.com;
location /web
proxy_pass http://static.test2.com/web;
server
listen 80;
server_name static.test2.com;
location /
root D:/resource/;
以上配置可以访问: http://static.test.com/web/test.html。
解析如下 :
提取路径: /web/test.html,去掉 /web, 得到 /test.html,跟proxy_pass拼在一起,得到
http://static.test2.com/web/test.html。
示例4:
如果location使用正则匹配,则proxy_pass只允许使用没有带/后缀的域名配置,否则会报错。
server
listen 80;
server_name static.test.com;
location ~/web
proxy_pass http://static.test2.com;
server
listen 80;
server_name static.test2.com;
location /
root D:/resource/;
小结:
1. 当proxy_pass只配置域名,而且没有以/结尾,原始路径会保留,否则会截取掉再拼装路径。
2. 如果proxy_pass上下文用了正则,那么proxy_pass只允许使用不带/的域名配置。
在配置反向代理的时候,通常还会这样配置:
location ~/web
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://static.test2.com;
这主要是为了跟踪发起请求的客户端的真正ip地址,后端语言从header中获取ip地址。
nginx的全局变量
变量名称 | 说明 |
---|---|
args | 请求中的参数部分 |
content_length | 请求头中的Content-length字段 |
content_type | 请求头中的Content-Type字段 |
cookie_COOKIE | cookie COOKIE变量的值 |
document_root | 当前请求在root指令中指定的值 |
host | 请求主机头字段,否则为服务器名称 |
http_HEADER | http某个请求头,跟cookie_COOKIE使用类似 |
is_args | 如果有args参数,这个变量等于”?”,否则等于””,空值 |
http_user_agent | 客户端agent信息 |
http_cookie | 客户端cookie信息 |
query_string | 与args相同 |
request_method | 客户端请求的动作,通常为GET或POST |
remote_addr | 客户端的IP地址 |
remote_port | 客户端的端口 |
request_uri | 包含请求参数的原始URI,不包含主机名,如:”/path/hellp.jsp?item=1”。不能修改schemeHTTP方法(如http,https) |
server_protocol | 请求使用的协议,通常是HTTP/1.0或HTTP/1.1server_addr服务器地址,在完成一次系统调用后可以确定这个值server_name服务器名称server_port请求到达服务器的端口号 |
更详细的见官方文档: http://nginx.org/en/docs/varindex.html
参考
http://nginx.org/en/docs/varindex.html
http://www.cnblogs.com/lidabo/p/4169396.html
http://yuanhsh.iteye.com/blog/1321982
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html
http://www.linuxidc.com/Linux/2014-01/95493.htm
以上是关于nginx基础配置篇的主要内容,如果未能解决你的问题,请参考以下文章