阅读之前,建议先阅读初识 Nginx。 之后,我们来了解一下 Nginx 配置。

抽象来说,将 Nginx 配置为 Web 服务器就是定义处理哪些 URI 和如何处理这些URI 对应的请求。具体来说,就是定义一些虚拟服务器(Virtual Servers),控制具有特定 IP 和域名的请求。

更具体的来说, Nginx 通过定义一系列 locations 来控制对 URIS 的选择。每一个 location 定义了对映射到自己的请求的处理场景:返回一个文件或者代理请求,或者根据不同的错误代码返回不同的错误页面。另外,根据 URI 的不同,请求也可以被重定向到其它 server 或者 location 。

设置虚拟服务器server

Nginx 配置文件至少包含一个 server 命令 ,用来定义虚拟服务器。当请求到来时, Nginx 会首先选择一个虚拟服务器来处理该请求。

虚拟服务器定义在 http 上下文中的 server 中:

http {
    server {
        # Server configuration
    }
}

注意: http 中可以定义多个 server

server 配置块使用 listen 命令监听本机 IP 和端口号(包括 Unix domain socket and path),支持 IPv4、IPv6,IPv6地址需要用方括号括起来:

server {
    listen 127.0.0.1:8080;  # IPv4地址,8080端口
    # listen [2001:3CA1:10F:1A:121B:0:0:10]:80;   # IPv6地址,80端口
    # listen [::]:80;  # 听本机的所有IPv4与IPv6地址,80端口
    # The rest of server configuration
}

上述配置,如果不写端口号,默认使用80端口,如果不写 IP ,则监听本机所有 IP。

server_name:
如果多个 server 的 listen IP 和端口号一模一样, Nginx 通过请求头中的 Host 与 server_name 定义的主机名进行比较,来选择合适的虚拟服务器处理请求:

server {
    listen      80;
    server_name lufficc.com  www.lufficc.com;
    ...
}

server_name 的参数可以为:

1 完整的主机名,如:api.lufficc.com

2 含有通配符(含有 ),如:.lufficc.com 或 api.* 。
通配符只能在开头或结尾,而且只能与一个 . 相邻。www..example.org 和 w.example.org 均无效。 但是,可以使用正则表达式匹配这些名称,例如 ~^www…+.example.org$ 和 ~^w.*.example.org$ 。 而且 * 可以匹配多个部分。 名称 * .example.org 不仅匹配 www.example.org还匹配www.sub.example.org

3 正则表达式,以 ~ 开头。
对于正则表达式:Nginx 使用的正则表达式与 Perl 编程语言(PCRE)使用的正则表达式兼容。 要使用正则表达式,且必须以 ~ 开头。

命名的正则表达式可以捕获变量,然后使用:

server {
    server_name   ~^(www\.)?(?<domain>.+)$;

    location / {
        root   /sites/$domain;
    }
}

小括号 () 之间匹配的内容,也可以在后面通过 $1 来引用,$2 表示的是前面第二个 () 里的内容。因此上述内容也可写为:

server {
    server_name   ~^(www\.)?(.+)$;

    location / {
        root   /sites/$2;
    }
}

一个 server_name 示例:

server {
    listen      80;
    server_name api.lufficc.com  *.lufficc.com;
    ...
}

同样,如果多个名称匹配 Host 头部, Nginx 采用下列顺序选择:
1 完整的主机名,如 api.lufficc.com
2 最长的,且以 * 开头的通配名,如:.lufficc.com。
3 最长的,且以 * 结尾的通配名,如:api.

4 第一个匹配的正则表达式。(按照配置文件中的顺序)
即优先级:api.lufficc.com > .lufficc.com > api. > 正则。

如果 Host 头部不匹配任何一个 server_name ,Nginx 将请求路由到默认虚拟服务器。默认虚拟服务器是指:nginx.conf 文件中第一个 server 或者 显式用 default_server 声明:
server {
listen 80 default_server;

}


配置 location

URI 与 location 参数的匹配
当选择好 server 之后,Nginx 会根据 URIs 选择合适的 location 来决定代理请求或者返回文件。

location 指令接受两种类型的参数:
1 前缀字符串(路径名称)
对于前缀字符串参数, URIs 必须严格的以它开头。例如对于 /some/path/ 参数,可以匹配 /some/path/document.html ,但是不匹配 /my-site/some/path,因为 /my-site/some/path 不以 /some/path/ 开头。

location /some/path/ {
    ...
}

2 正则表达式
对于正则表达式,以 ~ 开头表示大小写敏感,以 ~* 开头表示大小写不敏感。注意路径中的 . 要写成 \. 。例如一个匹配以 .html 或者 .htm 结尾的 URI 的 location:

location ~ \.html? {
    ...
}

正则表达式的优先级大于前缀字符串。如果找到匹配的前缀字符串,仍继续搜索正则表达式,但如果前缀字符串以 ^~ 开头,则不再检查正则表达式。

具体的搜索匹配流程如下:
1 将 URI 与所有的前缀字符串进行比较。

2 = 修饰符表明 URI 必须与前缀字符串相等(不是开始,而是相等),如果找到,则搜索停止。

3 如果找到的最长前缀匹配字符串以 ^~ 开头,则不再搜索正则表达式是否匹配。

4 匹配的最长前缀字符串。

5 测试对比 URI 与正则表达式。

6 第一个匹配的正则表达式后停止。

7 如果没有正则表达式匹配,使用 4 存储的前缀字符串对应的 location。

= 修饰符拥有最高的优先级。如网站首页访问频繁,我们可以专门定义一个 location 来减少搜索匹配次数(因为搜索到 = 修饰的匹配的 location 将停止搜索),提高速度:

location = / {
    ...
}

静态文件和代理

location 也定义了如何处理匹配的请求:返回静态文件 或者 交给代理服务器处理。下面的例子中,第一个 location 返回 /data 目录中的静态文件,第二个 location 则将请求传递给 https://lufficc.com 域名的服务器处理:

server {
    location /images/ {
        root /data;
    }

    location / {
        proxy_pass https://lufficc.com;
    }
}

root 指令定义了静态文件的根目录,并且和 URI 拼接形成最终的本地文件路径。如请求 /images/example.png,则拼接后返回本地服务器文件 /data/images/example.png 。

proxy_pass 指令将请求传递到 URL 指向的代理服务器。让后将来自代理服务器的响应转发给客户端。 在上面的示例中,所有不以 /images / 开头的 URI 的请求都将传递给代理服务器处理。

比如我把 proxy_pass 设置为 https://www.baidu.com/,那么访问 http://search.lufficc.com/ 将得到百度首页一样的响应(页面)(感兴趣的童鞋可以自己试一试搜索功能,和百度没差别呢):

server{
      listen 80;
      server_name search.lufficc.com;
      location / {
              proxy_pass https://www.baidu.com;
      }
}

使用变量(Variables)

你可以使用变量来使 Nginx 在不同的请求下采用不同的处理方式。变量是在运行时计算的,用作指令的参数。 变量由 $ 开头的符号表示。 变量基于 Nginx 的状态定义信息,例如当前处理的请求的属性。

有很多预定义变量,例如核心的 HTTP 变量,你也可以使用 set,map 和 geo 指令定义自定义变量。 大多数变量在运行时计算,并包含与特定请求相关的信息。 例如,$remote_addr 包含客户端 IP 地址,$uri 保存当前URI值。

一些常用的变量如下:

……
一个简单的应用就是从 http 重定向到 https 时带上路径信息:

server{
       ...
       return      301 https://lufficc.com$request_uri;
       ...
}

返回特定状态码
如果你的网站上的一些资源永久移除了,最快最简洁的方法就是使用 return 指令直接返回:

location /wrong/url {
    return 404;
}

return 的第一个参数是响应代码。可选的第二个参数可以是重定向(对应于代码301,302,303和307)的 URL 或在响应正文中返回的文本。 例如:

location /permanently/moved/url {
    return 301 http://www.example.com/moved/here;
}

return 指令可以包含在 location 和 server 上下文中:

server{
      location / {
              return 404;
      }
}

或者:

server{
      ...
      return 404;
      location / {
          ...
      }
}

错误处理

error_page 命令可以配置特定错误码的错误页面,或者重定向到其他的页面。下面的示例将在 404 错误发生时返回 /404.html 页面。

error_page 404 /404.html;

error_page 命令定义了如何处理错误,因此不会直接返回,而 return 确实会立即返回。当代理服务器或者 Nginx 处理时产生相应的错误的代码,均会返回相应的错误页面。

在下面的示例中,当 Nginx 找不到页面时,它将使用代码301替换代码404,并将客户端重定向到 http://example.com/new/path.html 。 此配置很有用,比如当客户端仍尝试用旧的 URI 访问页面时,301代码通知浏览器页面已永久移除,并且需要自动替换为返回的新地址。

location /old/path.html {
    error_page 404 =301 http:/example.com/new/path.html;
}

重写 URI

rewrite 指令可以多次修改请求的 URI。rewrite 的第一个参数是 URI需要匹配的正则表达式,第二个参数是将要替换的 URI。第三个参数可选,指示是否继续可以重写或者返回重定向代码(301或302)。例如:

location /users/ {
    rewrite ^/users/(.*)$ /show?user=$1 break;
}

您可以在 server 和 location 上下文中包括多个 rewrite 指令。 Nginx 按照它们发生的顺序一个一个地执行指令。 当选择 server 时,server 中的 rewrite 指令将执行一次。

在 Nginx 处理一组 rewrite 指令之后,它根据新的 URI 选择 location 。 如果所选 location 仍旧包含 rewrite 指令,它们将依次执行。如果 URI 匹配所有,则在处理完所有定义的 rewrite 指令后,搜索新的 location .

以下示例将 rewrite 指令与 return 指令结合使用:

server {
    ...
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  last;
    return  403;
    ...
}

诸如 /download/some/media/file 的 URI 被改为 /download/some/mp3/file.mp3 。 由于 last 标志,后续指令(第二个 rewrite 指令和 return 指令)被跳过,但 Nginx 继续以更改后的 URI 处理请求。 类似地,诸如 /download/some/audio/file 的 URI 被替换为 /download/some/mp3/file.ra。 如果 URI 不匹配 rewrite 指令,Nginx 将403 错误代码返回给客户端。

last 与 break的区别是:
last : 在当前 server 或 location 上下文中停止执行 rewrite 指令,但是 Nginx 继续搜索与重写的URI匹配的 location,并应用新 location 中的任何 rewrite 指令(这意味着 URI 可能再次改变)。

break :停止当前上下文中 rewrite 指令的处理,并取消搜索与新 URI 匹配的 location。 不会执行新 location中的 rewrite 指令。


允许,限制ip访问

allow和deny这两个指令的意思是指,允许ip和限制ip

在此之前不得不提一下,这两个指令是存在于ngx_http_access_module模块之中的

allow
语法:allow address |CIDR|unix:|all:
默认值:None
可以使用的标签区间:http,server,location,limit_except
允许一个ip或者ip段访问

deny
语法:deny address |CIDR|unix:|all:
默认值:None
可以使用的标签区间:http,server,location,limit_except
禁止一个ip或者ip段访问

eg:

location / {
	deny  192.168.1.1;
	allow 192.168.1.0/24;
	allow 10.1.1.0/16;
	allow 2001:0db8::/32;
	deny  all;
}

为什么最后会有斜杠呢,其实这是表示ip段的意思

屏蔽单个IP的命令是

deny 192.168.1.1
#封整个段即从123.0.0.1到123.255.255.254的命令
deny 123.0.0.0/8
#封IP段即从123.45.0.1到123.45.255.254的命令
deny 124.45.0.0/16
#封IP段即从123.45.6.1到123.45.6.254的命令是
deny 123.45.6.0/2412345678

也就是说,如果最后的斜杠后的数值:
8:匹配后三位最大值的
16:匹配后两位最大值的
24:匹配后一位最大值的


nginx 跨域

由于浏览器的安全限制,前端js代码无法直接访问不同域下的资源。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

跨域的解决方案有很多,目前常用的方案是通过nginx代理服务器给返回的响应头添加cors跨域配置项来解决。

在此对nginx配置add_header进行说明:
格式:add_header name value [always];
name是添加的头名称,value是对应的值,always可选(下面会详细说明 )。例如:

 location / {
       root /product/ftpfile/img/;
       #实际生产中*应该改为允许跨域的域名
       add_header Access-Control-Allow-Origin * always;
 }

在不添加always的情况下,add_header只对响应码为200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13), 308 (1.13.0)这些生效(括号内是nginx版本)。也就是说当服务端返回响应异常,响应码不是上述之一的话,即使nginx有配跨域头信息,浏览器仍然会显示跨域错误。原因就是因为nginx对异常响应码添加add_header无效。

实际工作中往往前端需要捕获服务端异常响应,这时在nginx跨域add_header上加上always,使nginx对任何响应码生效。


使用expire设置客户端缓存

在访问量比较大的网站中,利用客户端来缓存网站上不经常变更的图片,是给服务器减压的一个很方便且实用的做法。
比如,网站的 logo, 企业上传的 各种资格证书的图片,甚至有些商品的效果大图,只是不是经常变更的,大都可以让其存在客户端,提高访问速度,减小服务器的压力。
对nginx 来说,实现的方法很简单,只要在location段中,使用 expires 就可以了。

格式:
expires 30s; //表示把数据缓存30秒
expires 30m;//表示把数据缓存30分
expires 10h;//表示把数据缓存10小时
expires 1d;//表示把数据缓存1天

比如,我想把网站上的图片都让客户端来缓存3天
在nginx 中配置如下

location ~* \.(gif|jpg|jpeg|png) {
	root  /var/mywww/html/public/
	expires 3d;
}

nginx实现反向代理

1.什么是反向代理
通常的代理服务器,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中由代理服务器向Internet上的web服务器发起请求,最终达到客户机上网的目的(也就是正向代理)。
而反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
如下图:
Nginx进阶-配置文件-LMLPHP

Nginx只做请求的转发,后台有多个http服务器提供服务,nginx的功能就是把请求转发给后面的服务器,决定把请求转发给谁。
2、安装tomcat2个,现在我们模拟的话服务器就采用tomcat来模拟。
安装tomcat的过程就不介绍了,在http://blog.csdn.net/u013144287/article/details/78499485过程中有介绍,
1)创建一个tomcat目录mkdir -p /usr/local/tomcats
在此目录下安装两个tomcat如图所示:

2)修改tomcat2的端口号,vi ./tomcat2/conf/server.xml

<Server port="8006" shutdown="SHUTDOWN">
<Connector port="8081" protocol="HTTP/1.1"               connectionTimeout="20000"               redirectPort="8443" /><Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />

修改此3处端口号,分别在原来基础上加1,然后wq保存,启动两台tomcat

3、需求
通过访问不同的域名访问运行在tomcat不同端口的服务器,中间使用nginx反向代理服务器
需要修改hosts文件进行配置如下:
8080.zcinfo.com 访问运行8080端口的tomcat
8082.zcinfo.com 访问运行8081端口的tomcat
如图所示:hosts目录是:C:\Windows\System32\drivers\etc
Nginx进阶-配置文件-LMLPHP

4、Nginx的配置
在Nginx的配置文件里面加入如下配置

   upstream tomcatserver1 {
	server 192.168.3.43:8080;
    }
    upstream tomcatserver2 {
	server 192.168.3.43:8082;
    }
   server {
        listen       80;
        server_name  8080.zcinfo.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass   http://tomcatserver1;
            index  index.html index.htm;
        }
    }
    server {
        listen       80;
        server_name  8082.zcinfo.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass   http://tomcatserver2;
            index  index.html index.htm;
        }
    }

重启nginx使配置生效

5、测试

Nginx进阶-配置文件-LMLPHP
Nginx进阶-配置文件-LMLPHP
nginx反向代理成功


nginx实现负载均衡
1、什么是负载均衡?
负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

2、需求
nginx作为负载均衡服务器,用户请求先到达nginx,再由nginx根据负载配置将请求转发至tomcat服务器。
nginx负载均衡服务器:192.168.3.43
tomcat1服务器:192.168.3.43:8080
tomcat2服务器:192.168.3.43:8081

3、nginx的配置

  upstream tomcatserver1 {
	server 192.168.3.43:8080;
        server 192.168.3.43:8082; #多加了此台服务器
 }
    upstream tomcatserver2 {
	server 192.168.3.43:8082;
    }
   server {
        listen       80;
        server_name  8080.zcinfo.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass   http://tomcatserver1;
            index  index.html index.htm;
        }
    }
    server {
        listen       80;
        server_name  8082.zcinfo.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass   http://tomcatserver2;
            index  index.html index.htm;
        }
    }

如果两台服务器性能差不多这样设置重启nginx就行了,但是现在假如两台服务器性能不一样,还需要设置性能权重,让性能高服务器做更多事情。只需要加入weight=?就行了,如下:

upstream tomcatserver1 {
	server 192.168.3.43:8080 weight=2;
        server 192.168.3.43:8082 weight=1;
 }
    upstream tomcatserver2 {
	server 192.168.3.43:8082;
    }
   server {
        listen       80;
        server_name  8080.zcinfo.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass   http://tomcatserver1;
            index  index.html index.htm;
        }
    }
    server {
        listen       80;
        server_name  8082.zcinfo.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass   http://tomcatserver2;
            index  index.html index.htm;
        }
    }

重新启动nginx,会发现8080出现了两次,8082出现一次这样轮循。

ps:关于nginx负载均衡的一些参数介绍例子
节点说明:
在http节点里添加:

#定义负载均衡设备的 Ip及设备状态
upstream myServer {

   server 127.0.0.1:9090 down;
   server 127.0.0.1:8080 weight=2;
   server 127.0.0.1:6060;
   server 127.0.0.1:7070 backup;
}

在需要使用负载的Server节点下添加

proxy_pass http://myServer;

upstream 每个设备的状态:


附录

常用正则(Perl风格)

全局变量

举个栗子
例如请求:http://localhost:88/test1/test2/test.php
$host=localhost
$server_port=88
$request_uri=/test1/test2/test.php
$document_uri=/test1/test2/test.php
$document_root=/var/www/html
$request_filename=/var/www/html/test1/test2/test.php


大部分内容转载自你真的了解如何把nginx配置为web服务器吗。加上,己搜集的一些nginx的相关配置,不定时更新。

10-04 16:04