Nginx的反相代理, 负载均衡

转自 http://freeloda.blog.51cto.com/2033581/1288553html

大纲前端

1、前言nginx

2、环境准备web

3、安装与配置Nginx正则表达式

4、Nginx之反向代理算法

5、Nginx之负载均衡apache

6、Nginx之页面缓存vim

7、Nginx之URL重写后端

8、Nginx之读写分离xcode

注,操做系统为 CentOS 6.4 x86_64 , Nginx 是版本是最新版的1.4.2,因此实验用到的软件请点击这里下载:http://yunpan.cn/QXIgqMmVmuZrm

 

1、前言

       在前面的几篇博文中咱们主要讲解了Nginx做为Web服务器知识点,主要的知识点有nginx的理论详解、nginx做为web服务器的操做讲解、nginx做为LNMP架构的讲解,不清楚的博友能够回头看看,在这一篇博客中咱们主要讲解, nginx的反向代理、负载均衡、缓存、URL重写以及读写分离详解。好了,下面咱们来具体说一说。

2、环境准备

1. 操做系统

  • CentOS 6.4 x86_64

2.软件版本

  • Nginx 1.4.2

3.实验拓扑

注,实验拓扑见下文。

4.安装yum源

1
2
3
[root@nginx ~] # rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
[root@web1 ~] # rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
[root@web2 ~] # rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

5.各节点时间同步

1
2
3
[root@nginx ~] # ntpdate 202.120.2.101
[root@web1 ~] # ntpdate 202.120.2.101
[root@web2 ~] # ntpdate 202.120.2.101

6.关闭防火墙与SELinux

1
2
3
4
5
6
7
8
9
10
11
12
[root@nginx ~] # service iptables stop
[root@nginx ~] # chkconfig iptables off 
[root@nginx ~] # getenforce 
Disabled
[root@web1 ~] # service iptables stop
[root@web1 ~] # chkconfig iptables off 
[root@web1 ~] # getenforce 
Disabled
[root@web2 ~] # service iptables stop
[root@web2 ~] # chkconfig iptables off 
[root@web2 ~] # getenforce 
Disabled

3、安装Nginx

1.解压

1
[root@nginx src] # tar xf nginx-1.4.2.tar.gz

2.新建nginx用户与组

1
2
3
4
[root@nginx src] # groupadd -g 108  -r nginx
[root@nginx src] # useradd -u 108 -r -g 108 nginx 
[root@nginx src] # id nginx 
uid=108(nginx) gid=108(nginx) 组=108(nginx)

3.准备编译配置文件

1
2
[root@nginx src] # yum install -y pcre-devel openssl-devel
[root@nginx nginx-1.4.2] # ./configure   --prefix=/usr   --sbin-path=/usr/sbin/nginx   --conf-path=/etc/nginx/nginx.conf   --error-log-path=/var/log/nginx/error.log   --http-log-path=/var/log/nginx/access.log   --pid-path=/var/run/nginx/nginx.pid    --lock-path=/var/lock/nginx.lock   --user=nginx   --group=nginx   --with-http_ssl_module   --with-http_flv_module   --with-http_stub_status_module   --with-http_gzip_static_module   --http-client-body-temp-path=/var/tmp/nginx/client/   --http-proxy-temp-path=/var/tmp/nginx/proxy/   --http-fastcgi-temp-path=/var/tmp/nginx/fcgi/   --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi   --http-scgi-temp-path=/var/tmp/nginx/scgi   --with-pcre

4.编译并安装

1
[root@nginx nginx-1.4.2] # make && make install

5.为nginx提供SysV init脚本

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
[root@nginx ~] # cat /etc/init.d/nginx
#!/bin/sh 
# nginx - this script starts and stops the nginx daemon 
# chkconfig:   - 85 15 
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \ 
#               proxy and IMAP/POP3 proxy server 
# processname: nginx 
# config:      /etc/nginx/nginx.conf 
# config:      /etc/sysconfig/nginx 
# pidfile:     /var/run/nginx.pid 
# Source function library. 
/etc/rc .d /init .d /functions 
# Source networking configuration. 
/etc/sysconfig/network 
# Check that networking is up. 
"$NETWORKING"  "no"  ] &&  exit 
nginx= "/usr/sbin/nginx" 
prog=$( basename  $nginx) 
NGINX_CONF_FILE= "/etc/nginx/nginx.conf" 
[ -f  /etc/sysconfig/nginx  ] && .  /etc/sysconfig/nginx 
lockfile= /var/lock/subsys/nginx 
make_dirs() { 
    # make required directories 
    user=`nginx -V 2>&1 |  grep  "configure arguments:"  sed  's/[^*]*--user=\([^ ]*\).*/\1/g'  -` 
    options=`$nginx -V 2>&1 |  grep  'configure arguments:'
    for  opt  in  $options;  do 
        if  [ ` echo  $opt |  grep  '.*-temp-path' ` ];  then 
            value=` echo  $opt |  cut  -d  "="  -f 2` 
            if  [ ! -d  "$value"  ];  then 
                # echo "creating" $value 
                mkdir  -p $value &&  chown  -R $user $value 
            fi 
        fi 
    done 
start() { 
     [ -x $nginx ] ||  exit 
     [ -f $NGINX_CONF_FILE ] ||  exit 
     make_dirs 
     echo  -n $ "Starting $prog: " 
     daemon $nginx -c $NGINX_CONF_FILE 
     retval=$? 
     echo 
     [ $retval - eq  0 ] &&  touch  $lockfile 
     return  $retval 
stop() { 
     echo  -n $ "Stopping $prog: " 
     killproc $prog -QUIT 
     retval=$? 
     echo 
     [ $retval - eq  0 ] &&  rm  -f $lockfile 
     return  $retval 
restart() { 
     configtest ||  return  $? 
     stop 
     sleep 
     start 
reload() { 
     configtest ||  return  $? 
     echo  -n $ "Reloading $prog: " 
     killproc $nginx -HUP 
     RETVAL=$? 
     echo 
force_reload() { 
     restart 
configtest() { 
   $nginx -t -c $NGINX_CONF_FILE 
rh_status() { 
     status $prog 
rh_status_q() { 
     rh_status > /dev/null  2>&1 
case  "$1"  in 
     start) 
         rh_status_q &&  exit 
         $1 
         ;; 
     stop) 
         rh_status_q ||  exit 
         $1 
         ;; 
     restart|configtest) 
         $1 
         ;; 
     reload) 
         rh_status_q ||  exit 
         $1 
         ;; 
     force-reload) 
         force_reload 
         ;; 
     status) 
         rh_status 
         ;; 
     condrestart|try-restart) 
         rh_status_q ||  exit 
             ;; 
     *) 
         echo  $ "Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" 
         exit 
esac

6.为此脚本赋予执行权限

1
[root@nginx ~] # chmod +x /etc/init.d/nginx

7.添加至服务管理列表,并让其开机自动启动

1
2
3
4
[root@nginx ~] # chkconfig --add nginx
[root@nginx ~] # chkconfig nginx on 
[root@nginx ~] # chkconfig nginx --list 
nginx              0:关闭    1:关闭    2:启用    3:启用    4:启用    5:启用    6:关闭

8.启动nginx

1
2
[root@nginx ~] # service nginx start
正在启动 nginx:                                           [肯定]

9.查看一下端口

1
2
[root@nginx ~] # netstat -ntlp | grep :80
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      3889 /nginx

10.测试一下

t1

好了,Nginx安装与配置就到这里,下面咱们来讲一说Nginx的反向代理。

4、Nginx之反向代理

在配置nginx反向代理之间咱们得先准备两台测试服务器,Web1与Web2。

1.安装httpd

1
2
[root@web1 ~] # yum install -y httpd
[root@web2 ~] # yum install -y httpd

2.提供测试页面

1
2
[root@web1 ~] # echo "<h1>web1.test.com</h1>" > /var/www/html/index.html
[root@web2 ~] # echo "<h1>web2.test.com</h1>" > /var/www/html/index.html

3.启动httpd服务

1
2
3
4
[root@web1 ~] # service httpd start
正在启动 httpd:                                           [肯定]
[root@web2 ~] # service httpd start
正在启动 httpd:                                           [肯定]

4.测试一下

t2

t3

5.简单说一下,正向代理与反向代理

(1).正向代理的概念

       正向代理,也就是传说中的代理,他的工做原理就像一个跳板,简单的说,我是一个用户,我访问不了某网站,可是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的网站,因而我先连上代理服务器,告诉他我须要那个没法访问网站的内容,代理服务器去取回来,而后返回给我。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。

       结论就是,正向代理 是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),而后代理向原始服务器转交请求并将得到的内容返回给客户端。客户端必需要进行一些特别的设置才能使用正向代理。

(2).反向代理的概念

继续举例:    
       例用户访问 http://www.test.com/readme,但www.test.com上并不存在readme页面,他是偷偷从另一台服务器上取回来,而后做为本身的内容返回用户,但用户并不知情。这里所提到的 www.test.com 这个域名对应的服务器就设置了反向代理功能。

       结论就是,反向代理正好相反,对于客户端而言它就像是原始服务器,而且客户端不须要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将得到的内容返回给客户端,就像这些内容本来就是它本身的同样。

(3).二者区别

用途上来说:

       正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径。正向代理还可使用缓冲特性减小网络使用率。反向代理的典型用途是将防火墙后面的服务器提供给Internet用户访问。反向代理还能够为后端的多台服务器提供负载平衡,或为后端较慢的服务器提供缓冲服务。另外,反向代理还能够启用高级URL策略和管理技术,从而使处于不一样web服务器系统的web页面同时存在于同一个URL空间下。

安全性来说:

       正向代理容许客户端经过它访问任意网站而且隐藏客户端自身,所以你必须采起安全措施以确保仅为通过受权的客户端提供服务。反向代理对外都是透明的,访问者并不知道本身访问的是一个代理。

6.nginx 代理模块

http 代理官方中文文档http://www.howtocn.org/nginx:nginx%E6%A8%A1%E5%9D%97%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C%E4%B8%AD%E6%96%87%E7%89%88:standardhttpmodules:httpproxy

说明:代理模块的指令有不少我这里只讲解重要的proxy_pass,想了解更多代理指令请参考官方中文文档。

这个模块能够转发请求到其余的服务器。HTTP/1.0没法使用keepalive(后端服务器将为每一个请求建立而且删除链接)。nginx为浏览器发送HTTP/1.1并为后端服务器发送HTTP/1.0,这样浏览器就能够为浏览器处理keepalive。     
以下例:

1
2
3
4
location / {
   proxy_pass        http: //localhost :8000;
   proxy_set_header  X-Real-IP  $remote_addr;
}

注意,当使用http proxy模块(甚至FastCGI),全部的链接请求在发送到后端服务器以前nginx将缓存它们,所以,在测量从后端传送的数据时,它的进度显示可能不正确。

实验拓扑:

nginx4

7.配置http反向代理

1
2
3
4
5
6
[root@nginx ~] # cd /etc/nginx/
[root@nginx nginx] # cp nginx.conf nginx.conf.bak #备份一个原配置文件
[root@nginx nginx] # vim nginx.conf
location / {
                proxy_pass      http: //192 .168.18.201;
        }

指令说明:proxy_pass

语法:proxy_pass URL
默认值:no       
使用字段:location, location中的if字段       
这个指令设置被代理服务器的地址和被映射的URI,地址可使用主机名或IP加端口号的形式,例如:
proxy_pass http://localhost:8000/uri/;

8.从新加载一下配置文件

1
2
3
4
[root@nginx ~] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

9.测试一下

t4

注,你们能够看到,当咱们访问192.168.18.208时,被代理从新定向到Web1上。

10.查看一下Web服务器日志

1
2
3
4
5
6
7
8
9
10
11
[root@web1 ~] # tail /var/log/httpd/access_log
192.168.18.208 - - [04 /Sep/2013 :00:14:20 +0800]  "GET /favicon.ico HTTP/1.0"  404 289  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
192.168.18.208 - - [04 /Sep/2013 :00:14:20 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
192.168.18.208 - - [04 /Sep/2013 :00:14:20 +0800]  "GET /favicon.ico HTTP/1.0"  404 289  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
192.168.18.138 - - [04 /Sep/2013 :00:14:45 +0800]  "GET / HTTP/1.1"  200 23  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
192.168.18.138 - - [04 /Sep/2013 :00:14:48 +0800]  "GET /favicon.ico HTTP/1.1"  404 289  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
192.168.18.208 - - [04 /Sep/2013 :00:14:55 +0800]  "GET /favicon.ico HTTP/1.0"  404 289  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
192.168.18.208 - - [04 /Sep/2013 :00:15:05 +0800]  "GET /favicon.ico HTTP/1.0"  404 289  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
192.168.18.208 - - [04 /Sep/2013 :00:15:13 +0800]  "GET /favicon.ico HTTP/1.0"  404 289  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
192.168.18.208 - - [04 /Sep/2013 :00:15:16 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
192.168.18.208 - - [04 /Sep/2013 :00:15:16 +0800]  "GET /favicon.ico HTTP/1.0"  404 289  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"

注,你们能够看到咱们这里的客户的IP全是,nginx代理服务器的IP,并非真实客户端的IP。下面咱们修改一下,让日志的IP显示真实的客户端的IP。

11.修改nginx配置文件

 

1
2
3
4
location / {
         proxy_pass      http: //192 .168.18.201;
         proxy_set_header  X-Real-IP  $remote_addr;  #加上这一行
}

指令说明proxy_set_header

语法:proxy_set_header header value 
默认值: Host and Connection 
使用字段:http, server, location 
这个指令容许将发送到被代理服务器的请求头从新定义或者增长一些字段。这个值能够是一个文本,变量或者它们的组合。proxy_set_header在指定的字段中没有定义时会从它的上级字段继承。

12.从新加载一下配置文件

1
2
3
4
[root@nginx ~] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

13.测试并查看日志

1
2
3
4
5
6
7
8
9
10
11
[root@web1 ~] # tail /var/log/httpd/access_log
192.168.18.208 - - [03 /Sep/2013 :16:26:18 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.208 - - [03 /Sep/2013 :16:26:18 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.208 - - [03 /Sep/2013 :16:26:18 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.208 - - [03 /Sep/2013 :16:26:18 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.208 - - [03 /Sep/2013 :16:26:18 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.208 - - [03 /Sep/2013 :16:26:18 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.208 - - [03 /Sep/2013 :16:26:18 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.208 - - [03 /Sep/2013 :16:26:18 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.208 - - [03 /Sep/2013 :16:26:18 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.208 - - [03 /Sep/2013 :16:26:18 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"

注,你们能够看到日志记录的仍是代理的IP,没有显示真实客户端的IP,为何呢?咱们来看一下httpd的配置文件。

14.查看并修改httpd配置文件

[root@web1 ~]# vim /etc/httpd/conf/httpd.conf

t5

注,你们能够这里记录日志的参数仍是%h,下面咱们修改一下参数。

t6

注,这是修改后的参数,将h%修改成%{X-Real-IP}i,好的下面咱们再来测试一下。

15.重启并测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@web1 ~] # service httpd restart
中止 httpd:                                               [肯定]
正在启动 httpd:                                           [肯定]
[root@web1 ~] # tail /var/log/httpd/access_log
192.168.18.138 - - [03 /Sep/2013 :17:09:14 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [03 /Sep/2013 :17:09:14 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [03 /Sep/2013 :17:09:15 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [03 /Sep/2013 :17:09:15 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [03 /Sep/2013 :17:09:15 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [03 /Sep/2013 :17:09:15 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [03 /Sep/2013 :17:09:15 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [03 /Sep/2013 :17:09:15 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [03 /Sep/2013 :17:09:15 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [03 /Sep/2013 :17:09:15 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"

注,你们能够看到如今的日志里记录的IP地址就是真实的客户端地址了。好了,到这里Nginx代理后端一台服务器就演示到这里,下面咱们继续说。

5、Nginx之负载均衡

注,你们能够看到,因为咱们网站是发展初期,nginx只代理了后端一台服务器,但因为咱们网站名气大涨访问的人愈来愈多一台服务器实在是顶不住,因而咱们加了多台服务器,那么多台服务器又怎么配置代理呢,咱们这里以两台服务器为案例,为你们作演示。

1.upstream 负载均衡模块说明

案例:

下面设定负载均衡的服务器列表。

1
2
3
4
5
6
7
8
9
10
11
12
upstream  test .net{
ip_hash;
server 192.168.10.13:80;
server 192.168.10.14:80  down;
server 192.168.10.15:8009  max_fails=3  fail_timeout=20s;
server 192.168.10.16:8080;
}
server {
   location / {
     proxy_pass  http: //test .net;
   }
}

       upstream是Nginx的HTTP Upstream模块,这个模块经过一个简单的调度算法来实现客户端IP到后端服务器的负载均衡。在上面的设定中,经过upstream指令指定了一个负载均衡器的名称test.net。这个名称能够任意指定,在后面须要用到的地方直接调用便可。

2.upstream 支持的负载均衡算法

Nginx的负载均衡模块目前支持4种调度算法,下面进行分别介绍,其中后两项属于第三方调度算法。  

  • 轮询(默认)。每一个请求按时间顺序逐一分配到不一样的后端服务器,若是后端某台服务器宕机,故障系统被自动剔除,使用户访问不受影响。Weight 指定轮询权值,Weight值越大,分配到的访问机率越高,主要用于后端每一个服务器性能不均的状况下。

  • ip_hash。每一个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。

  • fair。这是比上面两个更加智能的负载均衡算法。此种算法能够依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx自己是不支持fair的,若是须要使用这种调度算法,必须下载Nginx的upstream_fair模块。

  • url_hash。此方法按访问url的hash结果来分配请求,使每一个url定向到同一个后端服务器,能够进一步提升后端缓存服务器的效率。Nginx自己是不支持url_hash的,若是须要使用这种调度算法,必须安装Nginx 的hash软件包。

3.upstream 支持的状态参数

在HTTP Upstream模块中,能够经过server指令指定后端服务器的IP地址和端口,同时还能够设定每一个后端服务器在负载均衡调度中的状态。经常使用的状态有:      

  • down,表示当前的server暂时不参与负载均衡。

  • backup,预留的备份机器。当其余全部的非backup机器出现故障或者忙的时候,才会请求backup机器,所以这台机器的压力最轻。

  • max_fails,容许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。

  • fail_timeout,在经历了max_fails次失败后,暂停服务的时间。max_fails能够和fail_timeout一块儿使用。

注,当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight和backup。

4.实验拓扑

nginx3

5.配置nginx负载均衡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@nginx ~] # vim /etc/nginx/nginx.conf
upstream webservers {
       server 192.168.18.201 weight=1;
       server 192.168.18.202 weight=1;
   }
   server {
       listen       80;
       server_name  localhost;
       #charset koi8-r;
       #access_log  logs/host.access.log  main;
       location / {
               proxy_pass      http: //webservers ;
               proxy_set_header  X-Real-IP  $remote_addr;
       }
}

注,upstream是定义在server{ }以外的,不能定义在server{ }内部。定义好upstream以后,用proxy_pass引用一下便可。

6.从新加载一下配置文件

1
2
3
4
[root@nginx ~] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

7.测试一下

t7

t8

注,你们能够不断的刷新浏览的内容,能够发现web1与web2是交替出现的,达到了负载均衡的效果。

8.查看一下Web访问服务器日志

Web1:

1
2
3
4
5
6
7
8
9
10
11
[root@web1 ~] # tail /var/log/httpd/access_log
192.168.18.138 - - [04 /Sep/2013 :09:41:58 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:41:58 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:41:59 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:41:59 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:42:00 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:42:00 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:42:00 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:44:21 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:44:22 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:44:22 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"

Web2:

先修改一下,Web服务器记录日志的格式。

1
2
3
4
5
[root@web2 ~] # vim /etc/httpd/conf/httpd.conf
LogFormat  "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""  combined
[root@web2 ~] # service httpd restart
中止 httpd:                                               [肯定]
正在启动 httpd:                                           [肯定]

接着,再访问屡次,继续查看日志。

1
2
3
4
5
6
7
8
9
10
11
[root@web2 ~] # tail /var/log/httpd/access_log
192.168.18.138 - - [04 /Sep/2013 :09:50:28 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:50:28 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:50:28 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:50:28 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:50:28 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:50:28 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:50:28 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:50:28 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:50:29 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
192.168.18.138 - - [04 /Sep/2013 :09:50:29 +0800]  "GET / HTTP/1.0"  200 23  "-"  "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"

注,你们能够看到,两台服务器日志都记录是192.168.18.138访问的日志,也说明了负载均衡配置成功。

9.配置nginx进行健康状态检查

  • max_fails,容许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。

  • fail_timeout,在经历了max_fails次失败后,暂停服务的时间。max_fails能够和fail_timeout一块儿使用,进行健康状态检查。

1
2
3
4
5
[root@nginx ~] # vim /etc/nginx/nginx.conf
upstream webservers {
         server 192.168.18.201 weight=1 max_fails=2 fail_timeout=2;
         server 192.168.18.202 weight=1 max_fails=2 fail_timeout=2;
     }

10.从新加载一下配置文件

1
2
3
4
[root@nginx ~] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

11.中止服务器并测试

1
2
3
先中止Web1,进行测试。
[root@web1 ~] # service httpd stop
中止 httpd:                                               [肯定]

t8

注,你们能够看到,如今只能访问Web2,再从新启动Web1,再次访问一下。

1
2
[root@web1 ~] # service httpd start
正在启动 httpd:                                           [肯定]

t7

t8

注,你们能够看到,如今又能够从新访问,说明nginx的健康状态查检配置成功。但你们想一下,若是不幸的是全部服务器都不能提供服务了怎么办,用户打开页面就会出现出错页面,那么会带来用户体验的下降,因此咱们能不能像配置LVS是配置sorry_server呢,答案是能够的,但这里不是配置sorry_server而是配置backup。

12.配置backup服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@nginx ~] # vim /etc/nginx/nginx.conf
server {
                 listen 8080;
                 server_name localhost;
                 root  /data/www/errorpage ;
                 index index.html;
         }
upstream webservers {
         server 192.168.18.201 weight=1 max_fails=2 fail_timeout=2;
         server 192.168.18.202 weight=1 max_fails=2 fail_timeout=2;
         server 127.0.0.1:8080 backup;
     }
[root@nginx ~] # mkdir -pv /data/www/errorpage
[root@nginx errorpage] # cat index.html
<h1>Sorry......< /h1 >

13.从新加载配置文件

1
2
3
4
[root@nginx errorpage] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

14.关闭Web服务器并进行测试

1
2
3
4
[root@web1 ~] # service httpd stop
中止 httpd:                                               [肯定]
[root@web2 ~] # service httpd stop
中止 httpd:                                               [肯定]

t9

注,你们能够看到,当全部服务器都不能工做时,就会启动备份服务器。好了,backup服务器就配置到这里,下面咱们来配置ip_hash负载均衡。

15.配置ip_hash负载均衡

  • ip_hash,每一个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。(通常电子商务网站用的比较多)

1
2
3
4
5
6
7
[root@nginx ~] # vim /etc/nginx/nginx.conf
upstream webservers {
         ip_hash;
         server 192.168.18.201 weight=1 max_fails=2 fail_timeout=2;
         server 192.168.18.202 weight=1 max_fails=2 fail_timeout=2;
         #server 127.0.0.1:8080 backup;
     }

注,当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能有backup。(有人可能会问,为何呢?你们想啊,若是负载均衡把你分配到backup服务器上,你能访问到页面吗?不能,因此了不能配置backup服务器)

16.从新加载一下服务器

1
2
3
4
[root@nginx ~] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

17.测试一下

t10

注,你们能够看到,你不断的刷新页面一直会显示的民Web2,说明ip_hash负载均衡配置成功。下面咱们来统计一下Web2的访问链接数。

18.统计Web2的访问链接数

1
2
[root@web2 ~] # netstat -an | grep :80 | wc -l
304

注,你不断的刷新,链接数会愈来愈多。好了,nginx的负载均衡就所有演示到这里下面咱们来讲一说,页面缓存。

6、Nginx之页面缓存

1.指令说明

proxy_cache_path

语法:proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time] [max_size=size];  
默认值:None  
使用字段:http  
指令指定缓存的路径和一些其余参数,缓存的数据存储在文件中,而且使用代理url的哈希值做为关键字与文件名。levels参数指定缓存的子目录数,例如:

1
proxy_cache_path   /data/nginx/cache   levels=1:2   keys_zone=one:10m;

文件名相似于:

1
/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c

levels指定目录结构,可使用任意的1位或2位数字做为目录结构,如 X, X:X,或X:X:X 例如: “2”, “2:2”, “1:1:2“,可是最多只能是三级目录。  
全部活动的key和元数据存储在共享的内存池中,这个区域用keys_zone参数指定。one指的是共享池的名称,10m指的是共享池的大小。  
注意每个定义的内存池必须是不重复的路径,例如:

1
2
3
proxy_cache_path   /data/nginx/cache/one     levels=1      keys_zone=one:10m;
proxy_cache_path   /data/nginx/cache/two     levels=2:2    keys_zone=two:100m;
proxy_cache_path   /data/nginx/cache/three   levels=1:1:2  keys_zone=three:1000m;

若是在inactive参数指定的时间内缓存的数据没有被请求则被删除,默认inactive为10分钟。一个名为cache manager的进程控制磁盘的缓存大小,它被用来删除不活动的缓存和控制缓存大小,这些都在max_size参数中定义,当目前缓存的值超出max_size指定的值以后,超过其大小后最少使用数据(LRU替换算法)将被删除。内存池的大小按照缓存页面数的比例进行设置,一个页面(文件)的元数据大小按照操做系统来定,如FreeBSD/i386下为64字节,FreeBSD/amd64下为128字节。

proxy_cache

语法:proxy_cache zone_name;  
默认值:None  
使用字段:http, server, location  
设置一个缓存区域的名称,一个相同的区域能够在不一样的地方使用。  
在0.7.48后,缓存遵循后端的”Expires”, “Cache-Control: no-cache”, “Cache-Control: max-age=XXX”头部字段,0.7.66版本之后,”Cache-Control:“private”和”no-store”头一样被遵循。nginx在缓存过程当中不会处理”Vary”头,为了确保一些私有数据不被全部的用户看到,后端必须设置 “no-cache”或者”max-age=0”头,或者proxy_cache_key包含用户指定的数据如$cookie_xxx,使用cookie的值做为proxy_cache_key的一部分能够防止缓存私有数据,因此能够在不一样的location中分别指定proxy_cache_key的值以便分开私有数据和公有数据。  
缓存指令依赖代理缓冲区(buffers),若是proxy_buffers设置为off,缓存不会生效。

proxy_cache_valid

语法:proxy_cache_valid reply_code [reply_code …] time;  
默认值:None  
使用字段:http, server, location  
为不一样的应答设置不一样的缓存时间,例如:

1
2
proxy_cache_valid  200 302  10m;
proxy_cache_valid  404      1m;

为应答代码为200和302的设置缓存时间为10分钟,404代码缓存1分钟。  
若是只定义时间:

1
proxy_cache_valid 5m;

那么只对代码为200, 301和302的应答进行缓存。  
一样可使用any参数任何应答。

1
2
3
proxy_cache_valid  200 302 10m;
proxy_cache_valid  301 1h;
proxy_cache_valid  any 1m;

2.定义一个简单nginx缓存服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@nginx ~] # vim /etc/nginx/nginx.conf
proxy_cache_path  /data/nginx/cache/webserver  levels=1:2 keys_zone=webserver:20m max_size=1g;
    server {
        listen       80;
        server_name  localhost;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
                proxy_pass      http: //webservers ;
                proxy_set_header  X-Real-IP  $remote_addr;
                proxy_cache webserver;
                proxy_cache_valid 200 10m;
        }
}

3.新建缓存目录

1
[root@nginx ~] # mkdir -pv /data/nginx/cache/webserver

4.从新加载一下配置文件

1
2
3
4
[root@nginx webserver] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

5.下面咱们来测试一下(谷歌浏览器)

t11

注,你们用谷歌浏览器测试的时候,能够按F12调用开发工具,选择Network选项,咱们能够看到,Response Headers,在这里咱们能够看到,咱们请求的是不是缓存,但如今还看不到,下面咱们来配置一下,再来测试。

6. 缓存变量说明

$server_addr

服务器地址,在完成一次系统调用后能够肯定这个值,若是要绕开系统调用,则必须在listen中指定地址而且使用bind参数。

$upstream_cache_status

0.8.3版本中其值可能为:

  • MISS 未命中

  • EXPIRED - expired。请求被传送到后端。

  • UPDATING - expired。因为proxy/fastcgi_cache_use_stale正在更新,将使用旧的应答。

  • STALE - expired。因为proxy/fastcgi_cache_use_stale,后端将获得过时的应答。

  • HIT 命中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@nginx ~] # vim /etc/nginx/nginx.conf
proxy_cache_path  /data/nginx/cache/webserver  levels=1:2 keys_zone=webserver:20m max_size=1g;
     server {
         listen       80;
         server_name  localhost;
         #charset koi8-r;
         #access_log  logs/host.access.log  main;
        #增长两头部
         add_header X-Via $server_addr;
         add_header X-Cache $upstream_cache_status;
         location / {
                 proxy_pass      http: //webservers ;
                 proxy_set_header  X-Real-IP  $remote_addr;
                 proxy_cache webserver;
                 proxy_cache_valid 200 10m;
         }
}

7.从新加载一下配置文件

1
2
3
4
[root@nginx ~] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

8.测试一下

t12

注,从图中咱们能够看到,咱们访问的服务器是192.168.18.208,缓存命中。你们能够看到是否是很直观啊。下面咱们看一下缓存目录。

9.查看一下缓存目录

1
2
3
[root@nginx ~] # cd /data/nginx/cache/webserver/f/63/
[root@nginx 63] # ls
681ad4c77694b65d61c9985553a2763f

注,缓存目录里确实有缓存文件。好了,nginx缓存配置就到这边了,更多配置请根据须要看配置文档。下面咱们来讲一下,URL重写。

7、Nginx之URL重写

1.URL重写模块(Rewrite)

摘要

这个模块容许使用正则表达式重写URI(需PCRE库),而且能够根据相关变量重定向和选择不一样的配置。若是这个指令在server字段中指定,那么将在被请求的location肯定以前执行,若是在指令执行后所选择的location中有其余的重写规则,那么它们也被执行。若是在location中执行这个指令产生了新的URI,那么location又一次肯定了新的URI。这样的循环能够最多执行10次,超过之后nginx将返回500错误。

指令

break

语法:break  
默认值:none  
使用字段:server, location, if  
完成当前设置的规则,中止执行其余的重写指令。  
示例:

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

语法:if (condition) { … }  
默认值:none  
使用字段:server, location  
注意:在使用if指令以前请查看if is evil page而且尽可能考虑用try_files代替。  
判断一个条件,若是条件成立,则后面的大括号内的语句将执行,相关配置从上级继承。  
能够在判断语句中指定下列值:

  • 一个变量的名称;不成立的值为:空字符传”“或者一些用“0”开始的字符串。

  • 一个使用=或者!=运算符的比较语句。

  • 使用符号~*和~模式匹配的正则表达式:

  • ~为区分大小写的匹配。

  • ~*不区分大小写的匹配(firefox匹配FireFox)。

  • !~和!~*意为“不匹配的”。

  • 使用-f和!-f检查一个文件是否存在。

  • 使用-d和!-d检查一个目录是否存在。

  • 使用-e和!-e检查一个文件,目录或者软连接是否存在。

  • 使用-x和!-x检查一个文件是否为可执行文件。

正则表达式的一部分能够用圆括号,方便以后按照顺序用$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
26
27
28
if  ($http_user_agent ~ MSIE) {
   rewrite  ^(.*)$   /msie/ $1   break ;
}
                                                                                                                                                        
if  ($http_cookie ~*  "id=([^;] +)(?:;|$)"  ) {
   set   $ id   $1;
}
                                                                                                                                                        
if  ($request_method = POST ) {
   return  405;
}
                                                                                                                                                        
if  (!-f $request_filename) {
   break ;
   proxy_pass  http: //127 .0.0.1;
}
                                                                                                                                                        
if  ($slow) {
   limit_rate  10k;
}
                                                                                                                                                        
if  ($invalid_referer) {
   return    403;
}
                                                                                                                                                        
if  ($args ~ post=140){
   rewrite ^ http: //example .com/ permanent;
}

内置变量$invalid_referer用指令valid_referers指定。

return

语法:return code  
默认值:none  
使用字段:server, location, if  
这个指令结束执行配置语句并为客户端返回状态代码,可使用下列的值:204,400,402-406,408,410, 411, 413, 416与500-504。此外,非标准代码444将关闭链接而且不发送任何的头部。

rewrite

语法:rewrite regex replacement flag  
默认值:none  
使用字段:server, location, if  
按照相关的正则表达式与字符串修改URI,指令按照在配置文件中出现的顺序执行。  
能够在重写指令后面添加标记。  
若是替换的字符串以http://开头,请求将被重定向,而且再也不执行多余的rewrite指令。  
尾部的标记(flag)能够是如下的值:

  • last - 完成重写指令,以后搜索相应的URI或location。

  • break - 完成重写指令。

  • redirect - 返回302临时重定向,若是替换字段用http://开头则被使用。

  • permanent - 返回301永久重定向。

注意若是一个重定向是相对的(没有主机名部分),nginx将在重定向的过程当中使用匹配server_name指令的“Host”头或者server_name指令指定的第一个名称,若是头不匹配或不存在,若是没有设置server_name,将使用本地主机名,若是你老是想让nginx使用“Host”头,能够在server_name使用“*”通配符(查看http核心模块中的server_name)。例如:

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

可是若是咱们将其放入一个名为/download/的location中,则须要将last标记改成break,不然nginx将执行10次循环并返回500错误。

1
2
3
4
5
location  /download/  {
   rewrite  ^( /download/ .*) /media/ (.*)\..*$  $1 /mp3/ $2.mp3   break ;
   rewrite  ^( /download/ .*) /audio/ (.*)\..*$  $1 /mp3/ $2.ra    break ;
   return    403;
}

若是替换字段中包含参数,那么其他的请求参数将附加到后面,为了防止附加,能够在最后一个字符后面跟一个问号:

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

注意:大括号({和}),能够同时用在正则表达式和配置块中,为了防止冲突,正则表达式使用大括号须要用双引号(或者单引号)。例如要重写如下的URL:

1
/photos/123456

为:

1
/path/to/photos/12/1234/123456 .png

则使用如下正则表达式(注意引号):

1
rewrite   "/photos/([0-9] {2})([0-9] {2})([0-9] {2})"  /path/to/photos/ $1/$1$2/$1$2$3.png;

若是指定一个“?”在重写的结尾,Nginx将丢弃请求中的参数,即变量$args,当使用$request_uri$uri&$args时能够在rewrite结尾使用“?”以免nginx处理两次参数串。  
在rewrite中使用$request_uri将www.example.com重写到example.com:

1
2
3
4
server {
    server_name www.example.com;
    rewrite ^ http: //example .com$request_uri? permanent;
}

一样,重写只对路径进行操做,而不是参数,若是要重写一个带参数的URL,可使用如下代替:

1
2
3
if  ($args ^~ post=100){
   rewrite ^ http: //example .com /new-address .html? permanent;
}

注意$args变量不会被编译,与location过程当中的URI不一样(参考http核心模块中的location)。

rewrite_log

语法:rewrite_log on | off  
默认值:rewrite_log off  
使用字段:server, location, if  
变量:无  
启用时将在error log中记录notice 标记的重写日志。

set

语法:set variable value  
默认值:none  
使用字段:server, location, if  
指令设置一个变量并为其赋值,其值能够是文本,变量和它们的组合。  
你可使用set定义一个新的变量,可是不能使用set设置$http_xxx头部变量的值。

uninitialized_variable_warn

语法:uninitialized_variable_warn on|off  
默认值:uninitialized_variable_warn on  
使用字段:http, server, location, if  
开启或关闭在未初始化变量中记录警告日志。  
事实上,rewrite指令在配置文件加载时已经编译到内部代码中,在解释器产生请求时使用。  
这个解释器是一个简单的堆栈虚拟机,以下列指令:

1
2
3
4
5
6
7
8
location  /download/  {
   if  ($forbidden) {
     return    403;
   }
   if  ($slow) {
     limit_rate  10k;
   }
   rewrite  ^/(download/.*) /media/ (.*)\..*$  /$1 /mp3/ $2.mp3   break ;

将被编译成如下顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
variable $forbidden
checking to zero
recovery 403
completion of entire code
variable $slow
checking to zero
checkings of regular excodession
copying  "/"
copying $1
copying  "/mp3/"
copying $2
copying  ".mp3"
completion of regular excodession
completion of entire sequence

注意并无关于limit_rate的代码,由于它没有说起ngx_http_rewrite_module模块,“if”块能够相似”location”指令在配置文件的相同部分同时存在。  
若是$slow为真,对应的if块将生效,在这个配置中limit_rate的值为10k。  
指令:

1
rewrite  ^/(download/.*) /media/ (.*)\..*$  /$1 /mp3/ $2.mp3   break ;

若是咱们将第一个斜杠括入圆括号,则能够减小执行顺序:

1
rewrite  ^( /download/ .*) /media/ (.*)\..*$  $1 /mp3/ $2.mp3   break ;

以后的顺序相似以下:

1
2
3
4
5
6
7
checking regular excodession
copying $1
copying  "/mp3/"
copying $2
copying  ".mp3"
completion of regular excodession
completion of entire code
2.简单案例
注,因为配置文件内容较多,为了让你们看着方便,咱们备份一下配置文件,打开一个新的配置文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@nginx ~] # cd /etc/nginx/
[root@nginx nginx] # mv nginx.conf nginx.conf.proxy
[root@nginx nginx] # cp nginx.conf.bak nginx.conf
[root@nginx nginx] # vim /etc/nginx/nginx.conf
server {
       listen       80;
       server_name  localhost;
       #charset koi8-r;
       #access_log  logs/host.access.log  main;
       location / {
           root   html;
           index  index.html index.htm;
           rewrite ^ /bbs/ (.*)$ http: //192 .168.18.201 /forum/ $1;
       }
}
准备forum目录与测试文件
1
2
3
4
5
6
7
[root@web1 ~] # cd /var/www/html/
[root@web1 html] # ls
index.html
[root@web1 html] # mkdir forum
[root@web1 html] # cd forum/
[root@web1 forum] # vim index.html
<h1>forum page!< /h1 >

测试一下

t13

好了,下面咱们来测试一下rewrite重写。

3.从新加载一下配置文件
1
2
3
4
[root@nginx 63] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

4.测试一下

t14

注,你们能够从图中看出,status code 302指的是临时重定向,那就说明咱们rewrite重写配置成功。你们知道302是临时重定向而301是永久重定向,那么怎么实现永久重定向呢。通常服务器与服务器之间是临时重定向,服务器内部是永久重定向。下面咱们来演示一下永久重定向。

5.配置永久重定向

1
2
3
4
5
6
7
8
9
10
11
12
[root@nginx nginx] # vim /etc/nginx/nginx.conf
server {
         listen       80;
         server_name  localhost;
         #charset koi8-r;
         #access_log  logs/host.access.log  main;
         location / {
             root   html;
             index  index.html index.htm;
             rewrite ^ /bbs/ (.*)$  /forum/ $1;
         }
}
准备forum目录与测试文件
1
2
3
4
5
6
7
[root@nginx ~] # cd /usr/html/
[root@nginx html] # ls
50x.html  index.html
[root@nginx html] # mkdir forum
[root@nginx html] # cd forum/
[root@nginx forum] # vim index.html
<h1>192.168.18.208 forum page< /h1 >

6.从新加载一下配置文件

1
2
3
4
[root@nginx ~] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

7.测试一下

t16

注,你们从图中能够看到,咱们访问bbs/是直接帮咱们跳转到forum/下,这种本机的跳转就是永久重定向也叫隐式重定向。好了,rewrite重定向咱们就说到这里了,想要查询更多关于重定向的指令请参考官方文档。最后,咱们来讲一下读写分离。

8、Nginx之读写分离

1.实验拓扑

nginx3

       需求分析,前端一台nginx作负载均衡反向代理,后面两台httpd服务器。整个架构是提供BBS(论坛)服务,有一需求得实现读写分离,就是上传附件的功能,咱们上传的附件只能上传到Web1,而后在Web1上利用rsync+inotify实现附件同步,你们都知道rsync+inotify只能是主向从同步,不能双向同步。因此Web1可进行写操做,而Web2只能进行读操做,这就带来读写分离的需求,下面咱们就来讲一下,读写分离怎么实现。

2.WebDAV功能说明

       WebDAV (Web-based Distributed Authoring and Versioning) 一种基于 HTTP 1.1协议的通讯协议。它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法之外添加了一些新的方法,使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还能够支持文件的版本控制。这样咱们就能配置读写分离功能了,下面咱们来具体配置一下。

3.修改配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@nginx nginx] # vim /etc/nginx/nginx.conf
server {
         listen       80;
         server_name  localhost;
         #charset koi8-r;
         #access_log  logs/host.access.log  main;
         location / {
                 proxy_pass http: //192 .168.18.202;
                 if  ($request_method =  "PUT" ){
                         proxy_pass http: //192 .168.18.201;
                 }
         }
}

4.从新加载一下配置文件

1
2
3
4
[root@nginx ~] # service nginx reload
nginx: the configuration  file  /etc/nginx/nginx .conf syntax is ok
nginx: configuration  file  /etc/nginx/nginx .conf  test  is successful
从新载入 nginx:                                           [肯定]

5.配置httpd的WebDAV功能

1
[root@web1 ~] # vim /etc/httpd/conf/httpd.conf

t17

注,在<Directory "/var/www/html">下启用就行。

6.从新启动一下httpd

1
2
3
[root@web1 ~] # service httpd restart
中止 httpd:                                               [肯定]
正在启动 httpd:                                           [肯定]

7.测试一下

1
2
3
4
[root@nginx ~] # curl http://192.168.18.201
<h1>web1. test .com< /h1 >
[root@nginx ~] # curl http://192.168.18.202
<h1>web2. test .com< /h1 >

注,web1与web2访问都没问题。

1
2
3
4
5
6
7
8
9
10
[root@nginx ~] # curl -T /etc/issue  http://192.168.18.202
<!DOCTYPE HTML PUBLIC  "-//IETF//DTD HTML 2.0//EN" >
<html>< head >
<title>405 Method Not Allowed< /title >
< /head ><body>
<h1>Method Not Allowed< /h1 >
The requested method PUT is not allowed  for  the URL  /issue .
<hr>
<address>Apache /2 .2.15 (CentOS) Server at 192.168.18.202 Port 80< /address >
< /body >< /html >

注,咱们上传文件到,web2上时,由于web2只人读功能,因此没有开户WebDAV功能,因此显示是405 Method Not Allowed。  

1
2
3
4
5
6
7
8
9
10
11
[root@nginx ~] # curl -T /etc/issue  http://192.168.18.201
<!DOCTYPE HTML PUBLIC  "-//IETF//DTD HTML 2.0//EN" >
<html>< head >
<title>403 Forbidden< /title >
< /head ><body>
<h1>Forbidden< /h1 >
You don't have permission to access  /issue
on this server.
<hr>
<address>Apache /2 .2.15 (CentOS) Server at 192.168.18.201 Port 80< /address >
< /body >< /html >

注,咱们在Web1开启了WebDAV功能,但咱们目录是root目录是不容许apache用户上传的,因此显示的是403 Forbidden。下面咱们给apache受权,容许上传。

1
[root@web1 ~] # setfacl -m u:apache:rwx /var/www/html/

下面咱们再来测试一下,

1
2
3
4
5
6
7
8
9
10
[root@nginx ~] # curl -T /etc/issue  http://192.168.18.201
<!DOCTYPE HTML PUBLIC  "-//IETF//DTD HTML 2.0//EN" >
<html>< head >
<title>201 Created< /title >
< /head ><body>
<h1>Created< /h1 >
Resource  /issue  has been created.
<hr />
<address>Apache /2 .2.15 (CentOS) Server at 192.168.18.201 Port 80< /address >
< /body >< /html >

注,你们能够看到咱们成功的上传了文件,说明nginx读写分离功能配置完成。最后,咱们来查看一下上传的文件。

1
2
3
4
5
6
[root@web1 ~] # cd /var/www/html/
[root@web1 html] # ll
总用量 12
drwxr-xr-x 2 root   root   4096 9月   4 13:16 forum
-rw-r--r-- 1 root   root     23 9月   3 23:37 index.html
-rw-r--r-- 1 apache apache   47 9月   4 14:06 issue

好了,到这里nginx的反向代理、负载均衡、页面缓存、URL重写及读写分离就所有讲解完成。但愿你们有所收获,^_^……

相关文章
相关标签/搜索