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,都会涉及到几个相关的指令,如下表所示:

指令出现上下文说明
breakserver,location,if完成当前的规则集,不再处理rewrite指令
ifserver,location条件判断,不支持嵌套,不支持多个条件&&和
setserver,location,if用于定义一个变量,并给变量赋值。变量的值可以为文本、变量以及文本变量的联合。
returnserver,location,if该指令用于结束规则的执行并返回状态码给客户端
rewriteserver,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本条规则匹配完成后,终止匹配,整个匹配流程结束
redirect302临时重定向
permanent301永久重定向

学习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_COOKIEcookie COOKIE变量的值
document_root当前请求在root指令中指定的值
host请求主机头字段,否则为服务器名称
http_HEADERhttp某个请求头,跟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基础配置篇的主要内容,如果未能解决你的问题,请参考以下文章

nginx基础配置篇

Nginx详解七:Nginx基础篇之Nginx官方模块

nginx基础配置篇

Nginx详解九:Nginx基础篇之Nginx的访问控制

Nginx基础07:反向代理配置

Nginx基础07:反向代理配置