Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离具体解释[通俗易懂]

Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离具体解释

大家好,又见面了,我是全栈君。

大纲

一、前言

二、环境准备

三、安装与配置Nginx

四、Nginx之反向代理

五、Nginx之负载均衡

六、Nginx之页面缓存

七、Nginx之URL重写

八、Nginx之读写分离

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

一、前言

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

二、环境准备

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

三、安装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.查看一下port

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的反向代理。

四、Nginx之反向代理

在配置nginx反向代理之间我们得先准备两台測试server,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).正向代理的概念

       正向代理。也就是传说中的代理,他的工作原理就像一个跳板,简单的说。我是一个用户,我訪问不了某站点,可是我能訪问一个代理server。这个代理server呢,他能訪问那个我不能訪问的站点,于是我先连上代理server,告诉他我须要那个无法訪问站点的内容,代理server去取回来。然后返回给我。

从站点的角度,仅仅在代理server来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料。这取决于代理告不告诉站点。

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

(2).反向代理的概念

继续举例:    
       例用户訪问
http://www.test.com/readme,但www.test.com上并不存在readme页面。他是偷偷从另外一台server上取回来,然后作为自己的内容返回用户,但用户并不知情。这里所提到的 www.test.com 这个域名相应的server就设置了反向代理功能。

       结论就是,反向代理正好相反,对于client而言它就像是原始server。而且client不须要进行不论什么特别的设置。

client向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将推断向何处(原始server)转交请求。并将获得的内容返回给client。就像这些内容原本就是它自己的一样。

(3).两者差别

用途上来讲:

       正向代理的典型用途是为在防火墙内的局域网client提供訪问Internet的途径。正向代理还能够使用缓冲特性降低网络使用率。反向代理的典型用途是将防火墙后面的server提供给Internet用户訪问。

反向代理还能够为后端的多台server提供负载平衡。或为后端较慢的server提供缓冲服务。另外,反向代理还能够启用高级URL策略和管理技术。从而使处于不同webserver系统的web页面同一时候存在于同一个URL空间下。

安全性来讲:

       正向代理同意client通过它訪问随意站点而且隐藏client自身,因此你必须採取安全措施以确保仅为经过授权的client提供服务。反向代理对外都是透明的,訪问者并不知道自己訪问的是一个代理。

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,想了解很多其它代理指令请參考官方中文文档。

这个模块能够转发请求到其它的server。

HTTP/1.0无法使用keepalive(后端server将为每一个请求创建而且删除连接)。nginx为浏览器发送HTTP/1.1并为后端server发送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),全部的连接请求在发送到后端server之前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字段      
这个指令设置被代理server的地址和被映射的URI,地址能够使用主机名或IP加port号的形式,比如:
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.查看一下Webserver日志

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代理server的IP,并非真实client的IP。以下我们改动一下,让日志的IP显示真实的client的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
这个指令同意将发送到被代理server的请求头又一次定义或者添加一些字段。这个值能够是一个文本,变量或者它们的组合。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。没有显示真实client的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地址就是真实的client地址了。好了。到这里Nginx代理后端一台server就演示到这里,以下我们继续说。

五、Nginx之负载均衡

注,大家能够看到。因为我们站点是发展初期,nginx仅仅代理了后端一台server,但因为我们站点名气大涨訪问的人越来越多一台server实在是顶不住。于是我们加了多台server,那么多台server又怎么配置代理呢,我们这里以两台server为案例,为大家做演示。

1.upstream 负载均衡模块说明

案例:

以下设定负载均衡的server列表。

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模块。这个模块通过一个简单的调度算法来实现clientIP到后端server的负载均衡。

在上面的设定中,通过upstream指令指定了一个负载均衡器的名称test.net。这个名称能够随意指定,在后面须要用到的地方直接调用就可以。

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

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

 

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

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

  • fair。这是比上面两个更加智能的负载均衡算法。

    此种算法能够根据页面大小和载入时间长短智能地进行负载均衡,也就是根据后端server的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持fair的。假设须要使用这样的调度算法。必须下载Nginx的upstream_fair模块。

  • url_hash。

    此方法按訪问url的hash结果来分配请求,使每一个url定向到同一个后端server。能够进一步提高后端缓存server的效率。

    Nginx本身是不支持url_hash的,假设须要使用这样的调度算法,必须安装Nginx 的hash软件包。

3.upstream 支持的状态參数

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

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

  • backup。预留的备份机器。当其它全部的非backup机器出现问题或者忙的时候。才会请求backup机器,因此这台机器的压力最轻。

  • max_fails。同意请求失败的次数,默觉得1。当超过最大次数时。返回proxy_next_upstream 模块定义的错误。

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

注,当负载调度算法为ip_hash时。后端server在负载均衡调度中的状态不能是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訪问server日志

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:

先改动一下,Webserver记录日志的格式。

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)"

注,大家能够看到,两台server日志都记录是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.停止server并測试

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.配置backupserver

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.关闭Webserver并进行測试

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

t9

注。大家能够看到,当全部server都不能工作时。就会启动备份server。好了,backupserver就配置到这里,以下我们来配置ip_hash负载均衡。

15.配置ip_hash负载均衡

  • ip_hash,每一个请求按訪问IP的hash结果分配。这样来自同一个IP的訪客固定訪问一个后端server,有效攻克了动态网页存在的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时,后端server在负载均衡调度中的状态不能有backup。(有人可能会问,为什么呢?大家想啊,假设负载均衡把你分配到backupserver上。你能訪问到页面吗?不能,所以了不能配置backupserver)

16.又一次载入一下server

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的负载均衡就所有演示到这里以下我们来说一说,页面缓存。

六、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的哈希值作为keyword与文件名称。

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缓存server

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

server地址,在完毕一次系统调用后能够确定这个值,假设要绕开系统调用,则必须在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

注,从图中我们能够看到,我们訪问的server是192.168.18.208,缓存命中。大家能够看到是不是非常直观啊。

以下我们看一下缓存文件夹。

9.查看一下缓存文件夹

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

注。缓存文件夹里确实有缓存文件。好了。nginx缓存配置就到这边了,很多其它配置请依据须要看配置文档。以下我们来说一下,URL重写。

七、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  
这个指令结束运行配置语句并为client返回状态代码,能够使用下列的值: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是永久重定向,那么怎么实现永久重定向呢。一般server与server之间是暂时重定向。server内部是永久重定向。

以下我们来演示一下永久重定向。

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重定向我们就讲到这里了,想要查询很多其它关于重定向的指令请參考官方文档。最后。我们来说一下读写分离。

八、Nginx之读写分离

1.实验拓扑

nginx3

       需求分析。前端一台nginx做负载均衡反向代理,后面两台httpdserver。整个架构是提供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重写及读写分离就所有解说完毕。

希望大家有所收获,^_^……

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/115636.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • java函数式编程Function(java函数式编程实战)

    JAVA函数式编程背景常见的编程范式函数式编程的优劣JAVA8中为函数式编程引入的变化JAVA函数式编程可以简单概括基本函数Lambda表达式方法引用Stream流API创建操作中间操作终止从操作并行流级联表达式与柯里化收集器(终止操作因为内容较多提出来说明)Stream特性工程地址背景JAVA版本最新的目前已经发布到11了,但目前市面上大多数公司依然在使用Java7之前版本的语法,然而这些编…

  • 哈希表基本概念介绍及哈希冲突的处理方法(附源码)

    哈希表基本概念介绍及哈希冲突的处理方法(附源码)工科生一枚,热衷于底层技术开发,有强烈的好奇心,感兴趣内容包括单片机,嵌入式Linux,Uboot等,欢迎学习交流!爱好跑步,打篮球,睡觉。欢迎加我QQ1500836631(备注CSDN),一起学习交流问题,分享各种学习资料,电子书籍,学习视频等。文章目录哈希表和哈希函数的概念哈希函数的构造直接定址法数字分析法平方取中法折叠法除留余数法(常用)随机数法哈希函数的选择处理冲突的方法开放定址法再哈希法链地址法建立一个公共溢出区代码实现哈希表和哈希函数的概念  哈希表(散列表),是根据关键码值(Ke.

  • 项目复盘/总结模板

    项目复盘/总结模板复盘会议的安排、步骤及意义什么是复盘?为何要复盘?WHAT?复盘,是行动后的深刻反思和经验总结,是一个不断学习、总结、反思、提炼和持续提高的过程。复盘是企业文化、是行动学习、是提升组织智慧的重

  • pycharm激活码2022年(JetBrains全家桶)

    (pycharm激活码2022年)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

  • 芭芭农场自动脚本_农场游戏源码

    芭芭农场自动脚本_农场游戏源码特此声明:此版本校内开心农场外挂由python语言编写,运行平台为linux。本代码是修改网络上流传的源码而成,本人贴出此代码没有任何利益想法,只当学习交流之用,并感谢源码开发者!#!/usr/bin/envpython#encoding:utf-8#2009-8-21升级后importurllib,urllib2,cookielibimporttime,zlib,r

  • linux安装启动nginx_centos7 安装

    linux安装启动nginx_centos7 安装环境:VMware16pro,centos7解决:安装nginx前的准备安装gcc环境:在官网下载的nginx源码需要编译,所以需要gcc环境。yuminstallgcc-c++安装PCREpcre-develNginx的Rewrite模块和HTTP核心模块会使用到PCRE正则表达式语法。这里需要安装两个安装包pcre和pcre-devel。第一个安装包提供编译版本的库,而第二个提供开发阶段的头文件和编译项目的源代码。安装命令如下:yuminstall-ypcr

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号