大綱
一、前言
二、環(huán)境準(zhǔn)備
三、安裝與配置Nginx
四、Nginx之反向代理
五、Nginx之負(fù)載均衡
六、Nginx之頁(yè)面緩存
七、Nginx之URL重寫(xiě)
八、Nginx之讀寫(xiě)分離
注,操作系統(tǒng)為 CentOS 6.4 x86_64 , Nginx 是版本是最新版的1.4.2,所以實(shí)驗(yàn)用到的軟件請(qǐng)點(diǎn)擊這里下載:http:///QXIgqMmVmuZrm
一、前言
在前面的幾篇博文中我們主要講解了Nginx作為Web服務(wù)器知識(shí)點(diǎn),主要的知識(shí)點(diǎn)有nginx的理論詳解、nginx作為web服務(wù)器的操作講解、nginx作為L(zhǎng)NMP架構(gòu)的講解,不清楚的博友可以回頭看看,在這一篇博客中我們主要講解, nginx的反向代理、負(fù)載均衡、緩存、URL重寫(xiě)以及讀寫(xiě)分離詳解。好了,下面我們來(lái)具體說(shuō)一說(shuō)。
二、環(huán)境準(zhǔn)備
1. 操作系統(tǒng)
2.軟件版本
3.實(shí)驗(yàn)拓?fù)?/span>
注,實(shí)驗(yàn)拓?fù)湟?jiàn)下文。
4.安裝yum源
1 2 3 | [root@nginx ~]
[root@web1 ~]
[root@web2 ~]
|
5.各節(jié)點(diǎn)時(shí)間同步
1 2 3 | [root@nginx ~]
[root@web1 ~]
[root@web2 ~]
|
6.關(guān)閉防火墻與SELinux
1 2 3 4 5 6 7 8 9 10 11 12 | [root@nginx ~]
[root@nginx ~]
[root@nginx ~]
Disabled
[root@web1 ~]
[root@web1 ~]
[root@web1 ~]
Disabled
[root@web2 ~]
[root@web2 ~]
[root@web2 ~]
Disabled
|
三、安裝Nginx
1.解壓
2.新建nginx用戶(hù)與組
1 2 3 4 | [root@nginx src]
[root@nginx src]
[root@nginx src]
uid=108(nginx) gid=108(nginx) 組=108(nginx)
|
3.準(zhǔn)備編譯配置文件
1 2 | [root@nginx src]
[root@nginx nginx-1.4.2]
|
4.編譯并安裝
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 ~]
#!/bin/sh
. /etc/rc .d /init .d /functions
. /etc/sysconfig/network
[ "$NETWORKING" = "no" ] && exit 0
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() {
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
mkdir -p $value && chown -R $user $value
fi
fi
done
}
start() {
[ -x $nginx ] || exit 5
[ -f $NGINX_CONF_FILE ] || exit 6
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 1
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 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
;;
*)
echo $ "Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
exit 2
esac
|
6.為此腳本賦予執(zhí)行權(quán)限
7.添加至服務(wù)管理列表,并讓其開(kāi)機(jī)自動(dòng)啟動(dòng)
1 2 3 4 | [root@nginx ~]
[root@nginx ~]
[root@nginx ~]
nginx 0:關(guān)閉 1:關(guān)閉 2:啟用 3:啟用 4:啟用 5:啟用 6:關(guān)閉
|
8.啟動(dòng)nginx
1 2 | [root@nginx ~]
正在啟動(dòng) nginx: [確定]
|
9.查看一下端口
1 2 | [root@nginx ~]
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3889 /nginx
|
10.測(cè)試一下

好了,Nginx安裝與配置就到這里,下面我們來(lái)說(shuō)一說(shuō)Nginx的反向代理。
四、Nginx之反向代理
在配置nginx反向代理之間我們得先準(zhǔn)備兩臺(tái)測(cè)試服務(wù)器,Web1與Web2。
1.安裝httpd
1 2 | [root@web1 ~]
[root@web2 ~]
|
2.提供測(cè)試頁(yè)面
1 2 | [root@web1 ~]
[root@web2 ~]
|
3.啟動(dòng)httpd服務(wù)
1 2 3 4 | [root@web1 ~]
正在啟動(dòng) httpd: [確定]
[root@web2 ~]
正在啟動(dòng) httpd: [確定]
|
4.測(cè)試一下


5.簡(jiǎn)單說(shuō)一下,正向代理與反向代理
(1).正向代理的概念
正向代理,也就是傳說(shuō)中的代理,他的工作原理就像一個(gè)跳板,簡(jiǎn)單的說(shuō),我是一個(gè)用戶(hù),我訪(fǎng)問(wèn)不了某網(wǎng)站,但是我能訪(fǎng)問(wèn)一個(gè)代理服務(wù)器,這個(gè)代理服務(wù)器呢,他能訪(fǎng)問(wèn)那個(gè)我不能訪(fǎng)問(wèn)的網(wǎng)站,于是我先連上代理服務(wù)器,告訴他我需要那個(gè)無(wú)法訪(fǎng)問(wèn)網(wǎng)站的內(nèi)容,代理服務(wù)器去取回來(lái),然后返回給我。從網(wǎng)站的角度,只在代理服務(wù)器來(lái)取內(nèi)容的時(shí)候有一次記錄,有時(shí)候并不知道是用戶(hù)的請(qǐng)求,也隱藏了用戶(hù)的資料,這取決于代理告不告訴網(wǎng)站。
結(jié)論就是,正向代理 是一個(gè)位于客戶(hù)端和原始服務(wù)器(origin server)之間的服務(wù)器,為了從原始服務(wù)器取得內(nèi)容,客戶(hù)端向代理發(fā)送一個(gè)請(qǐng)求并指定目標(biāo)(原始服務(wù)器),然后代理向原始服務(wù)器轉(zhuǎn)交請(qǐng)求并將獲得的內(nèi)容返回給客戶(hù)端??蛻?hù)端必須要進(jìn)行一些特別的設(shè)置才能使用正向代理。
(2).反向代理的概念
繼續(xù)舉例:
例用戶(hù)訪(fǎng)問(wèn) http://www./readme,但www.上并不存在readme頁(yè)面,他是偷偷從另外一臺(tái)服務(wù)器上取回來(lái),然后作為自己的內(nèi)容返回用戶(hù),但用戶(hù)并不知情。這里所提到的 www. 這個(gè)域名對(duì)應(yīng)的服務(wù)器就設(shè)置了反向代理功能。
結(jié)論就是,反向代理正好相反,對(duì)于客戶(hù)端而言它就像是原始服務(wù)器,并且客戶(hù)端不需要進(jìn)行任何特別的設(shè)置??蛻?hù)端向反向代理的命名空間(name-space)中的內(nèi)容發(fā)送普通請(qǐng)求,接著反向代理將判斷向何處(原始服務(wù)器)轉(zhuǎn)交請(qǐng)求,并將獲得的內(nèi)容返回給客戶(hù)端,就像這些內(nèi)容原本就是它自己的一樣。
(3).兩者區(qū)別
從用途上來(lái)講:
正向代理的典型用途是為在防火墻內(nèi)的局域網(wǎng)客戶(hù)端提供訪(fǎng)問(wèn)Internet的途徑。正向代理還可以使用緩沖特性減少網(wǎng)絡(luò)使用率。反向代理的典型用途是將防火墻后面的服務(wù)器提供給Internet用戶(hù)訪(fǎng)問(wèn)。反向代理還可以為后端的多臺(tái)服務(wù)器提供負(fù)載平衡,或?yàn)楹蠖溯^慢的服務(wù)器提供緩沖服務(wù)。另外,反向代理還可以啟用高級(jí)URL策略和管理技術(shù),從而使處于不同web服務(wù)器系統(tǒng)的web頁(yè)面同時(shí)存在于同一個(gè)URL空間下。
從安全性來(lái)講:
正向代理允許客戶(hù)端通過(guò)它訪(fǎng)問(wèn)任意網(wǎng)站并且隱藏客戶(hù)端自身,因此你必須采取安全措施以確保僅為經(jīng)過(guò)授權(quán)的客戶(hù)端提供服務(wù)。反向代理對(duì)外都是透明的,訪(fǎng)問(wèn)者并不知道自己訪(fǎng)問(wèn)的是一個(gè)代理。
6.nginx 代理模塊
http 代理官方中文文檔:http://www./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
說(shuō)明:代理模塊的指令有很多我這里只講解重要的proxy_pass,想了解更多代理指令請(qǐng)參考官方中文文檔。
這個(gè)模塊可以轉(zhuǎn)發(fā)請(qǐng)求到其他的服務(wù)器。HTTP/1.0無(wú)法使用keepalive(后端服務(wù)器將為每個(gè)請(qǐng)求創(chuàng)建并且刪除連接)。nginx為瀏覽器發(fā)送HTTP/1.1并為后端服務(wù)器發(fā)送HTTP/1.0,這樣瀏覽器就可以為瀏覽器處理keepalive。
如下例:
1 2 3 4 | location / {
proxy_pass http: //localhost :8000;
proxy_set_header X-Real-IP $remote_addr;
}
|
注意,當(dāng)使用http proxy模塊(甚至FastCGI),所有的連接請(qǐng)求在發(fā)送到后端服務(wù)器之前nginx將緩存它們,因此,在測(cè)量從后端傳送的數(shù)據(jù)時(shí),它的進(jìn)度顯示可能不正確。
實(shí)驗(yàn)拓?fù)洌?/span>

7.配置http反向代理
1 2 3 4 5 6 | [root@nginx ~]
[root@nginx nginx]
[root@nginx nginx]
location / {
proxy_pass http: //192 .168.18.201;
}
|
指令說(shuō)明:proxy_pass
語(yǔ)法:proxy_pass URL
默認(rèn)值:no
使用字段:location, location中的if字段
這個(gè)指令設(shè)置被代理服務(wù)器的地址和被映射的URI,地址可以使用主機(jī)名或IP加端口號(hào)的形式,例如:proxy_pass http://localhost:8000/uri/;
8.重新加載一下配置文件
1 2 3 4 | [root@nginx ~]
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
9.測(cè)試一下

注,大家可以看到,當(dāng)我們?cè)L問(wèn)192.168.18.208時(shí),被代理重新定向到Web1上。
10.查看一下Web服務(wù)器日志
1 2 3 4 5 6 7 8 9 10 11 | [root@web1 ~]
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"
|
注,大家可以看到我們這里的客戶(hù)的IP全是,nginx代理服務(wù)器的IP,并不是真實(shí)客戶(hù)端的IP。下面我們修改一下,讓日志的IP顯示真實(shí)的客戶(hù)端的IP。
11.修改nginx配置文件
1 2 3 4 | location / {
proxy_pass http: //192 .168.18.201;
proxy_set_header X-Real-IP $remote_addr;
}
|
指令說(shuō)明:proxy_set_header
語(yǔ)法:proxy_set_header header value
默認(rèn)值: Host and Connection
使用字段:http, server, location
這個(gè)指令允許將發(fā)送到被代理服務(wù)器的請(qǐng)求頭重新定義或者增加一些字段。這個(gè)值可以是一個(gè)文本,變量或者它們的組合。proxy_set_header在指定的字段中沒(méi)有定義時(shí)會(huì)從它的上級(jí)字段繼承。
12.重新加載一下配置文件
1 2 3 4 | [root@nginx ~]
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
13.測(cè)試并查看日志
1 2 3 4 5 6 7 8 9 10 11 | [root@web1 ~]
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,沒(méi)有顯示真實(shí)客戶(hù)端的IP,為什么呢?我們來(lái)看一下httpd的配置文件。
14.查看并修改httpd配置文件
[root@web1 ~]# vim /etc/httpd/conf/httpd.conf

注,大家可以這里記錄日志的參數(shù)還是%h,下面我們修改一下參數(shù)。

注,這是修改后的參數(shù),將h%修改為%{X-Real-IP}i,好的下面我們?cè)賮?lái)測(cè)試一下。
15.重啟并測(cè)試
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [root@web1 ~]
停止 httpd: [確定]
正在啟動(dòng) httpd: [確定]
[root@web1 ~]
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)"
|
注,大家可以看到現(xiàn)在的日志里記錄的IP地址就是真實(shí)的客戶(hù)端地址了。好了,到這里Nginx代理后端一臺(tái)服務(wù)器就演示到這里,下面我們繼續(xù)說(shuō)。
五、Nginx之負(fù)載均衡
注,大家可以看到,由于我們網(wǎng)站是發(fā)展初期,nginx只代理了后端一臺(tái)服務(wù)器,但由于我們網(wǎng)站名氣大漲訪(fǎng)問(wèn)的人越來(lái)越多一臺(tái)服務(wù)器實(shí)在是頂不住,于是我們加了多臺(tái)服務(wù)器,那么多臺(tái)服務(wù)器又怎么配置代理呢,我們這里以?xún)膳_(tái)服務(wù)器為案例,為大家做演示。
1.upstream 負(fù)載均衡模塊說(shuō)明
案例:
下面設(shè)定負(fù)載均衡的服務(wù)器列表。
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模塊,這個(gè)模塊通過(guò)一個(gè)簡(jiǎn)單的調(diào)度算法來(lái)實(shí)現(xiàn)客戶(hù)端IP到后端服務(wù)器的負(fù)載均衡。在上面的設(shè)定中,通過(guò)upstream指令指定了一個(gè)負(fù)載均衡器的名稱(chēng)test.net。這個(gè)名稱(chēng)可以任意指定,在后面需要用到的地方直接調(diào)用即可。
2.upstream 支持的負(fù)載均衡算法
Nginx的負(fù)載均衡模塊目前支持4種調(diào)度算法,下面進(jìn)行分別介紹,其中后兩項(xiàng)屬于第三方調(diào)度算法。
輪詢(xún)(默認(rèn))。每個(gè)請(qǐng)求按時(shí)間順序逐一分配到不同的后端服務(wù)器,如果后端某臺(tái)服務(wù)器宕機(jī),故障系統(tǒng)被自動(dòng)剔除,使用戶(hù)訪(fǎng)問(wèn)不受影響。Weight 指定輪詢(xún)權(quán)值,Weight值越大,分配到的訪(fǎng)問(wèn)機(jī)率越高,主要用于后端每個(gè)服務(wù)器性能不均的情況下。
ip_hash。每個(gè)請(qǐng)求按訪(fǎng)問(wèn)IP的hash結(jié)果分配,這樣來(lái)自同一個(gè)IP的訪(fǎng)客固定訪(fǎng)問(wèn)一個(gè)后端服務(wù)器,有效解決了動(dòng)態(tài)網(wǎng)頁(yè)存在的session共享問(wèn)題。
fair。這是比上面兩個(gè)更加智能的負(fù)載均衡算法。此種算法可以依據(jù)頁(yè)面大小和加載時(shí)間長(zhǎng)短智能地進(jìn)行負(fù)載均衡,也就是根據(jù)后端服務(wù)器的響應(yīng)時(shí)間來(lái)分配請(qǐng)求,響應(yīng)時(shí)間短的優(yōu)先分配。Nginx本身是不支持fair的,如果需要使用這種調(diào)度算法,必須下載Nginx的upstream_fair模塊。
url_hash。此方法按訪(fǎng)問(wèn)url的hash結(jié)果來(lái)分配請(qǐng)求,使每個(gè)url定向到同一個(gè)后端服務(wù)器,可以進(jìn)一步提高后端緩存服務(wù)器的效率。Nginx本身是不支持url_hash的,如果需要使用這種調(diào)度算法,必須安裝Nginx 的hash軟件包。
3.upstream 支持的狀態(tài)參數(shù)
在HTTP Upstream模塊中,可以通過(guò)server指令指定后端服務(wù)器的IP地址和端口,同時(shí)還可以設(shè)定每個(gè)后端服務(wù)器在負(fù)載均衡調(diào)度中的狀態(tài)。常用的狀態(tài)有:
down,表示當(dāng)前的server暫時(shí)不參與負(fù)載均衡。
backup,預(yù)留的備份機(jī)器。當(dāng)其他所有的非backup機(jī)器出現(xiàn)故障或者忙的時(shí)候,才會(huì)請(qǐng)求backup機(jī)器,因此這臺(tái)機(jī)器的壓力最輕。
max_fails,允許請(qǐng)求失敗的次數(shù),默認(rèn)為1。當(dāng)超過(guò)最大次數(shù)時(shí),返回proxy_next_upstream 模塊定義的錯(cuò)誤。
fail_timeout,在經(jīng)歷了max_fails次失敗后,暫停服務(wù)的時(shí)間。max_fails可以和fail_timeout一起使用。
注,當(dāng)負(fù)載調(diào)度算法為ip_hash時(shí),后端服務(wù)器在負(fù)載均衡調(diào)度中的狀態(tài)不能是weight和backup。
4.實(shí)驗(yàn)拓?fù)?/span>

5.配置nginx負(fù)載均衡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [root@nginx ~]
upstream webservers {
server 192.168.18.201 weight=1;
server 192.168.18.202 weight=1;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http: //webservers ;
proxy_set_header X-Real-IP $remote_addr;
}
}
|
注,upstream是定義在server{ }之外的,不能定義在server{ }內(nèi)部。定義好upstream之后,用proxy_pass引用一下即可。
6.重新加載一下配置文件
1 2 3 4 | [root@nginx ~]
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
7.測(cè)試一下


注,大家可以不斷的刷新瀏覽的內(nèi)容,可以發(fā)現(xiàn)web1與web2是交替出現(xiàn)的,達(dá)到了負(fù)載均衡的效果。
8.查看一下Web訪(fǎng)問(wèn)服務(wù)器日志
Web1:
1 2 3 4 5 6 7 8 9 10 11 | [root@web1 ~]
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服務(wù)器記錄日志的格式。
1 2 3 4 5 | [root@web2 ~]
LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
[root@web2 ~]
停止 httpd: [確定]
正在啟動(dòng) httpd: [確定]
|
接著,再訪(fǎng)問(wèn)多次,繼續(xù)查看日志。
1 2 3 4 5 6 7 8 9 10 11 | [root@web2 ~]
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)"
|
注,大家可以看到,兩臺(tái)服務(wù)器日志都記錄是192.168.18.138訪(fǎng)問(wèn)的日志,也說(shuō)明了負(fù)載均衡配置成功。
9.配置nginx進(jìn)行健康狀態(tài)檢查
max_fails,允許請(qǐng)求失敗的次數(shù),默認(rèn)為1。當(dāng)超過(guò)最大次數(shù)時(shí),返回proxy_next_upstream 模塊定義的錯(cuò)誤。
fail_timeout,在經(jīng)歷了max_fails次失敗后,暫停服務(wù)的時(shí)間。max_fails可以和fail_timeout一起使用,進(jìn)行健康狀態(tài)檢查。
1 2 3 4 5 | [root@nginx ~]
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 ~]
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
11.停止服務(wù)器并測(cè)試
1 2 3 | 先停止Web1,進(jìn)行測(cè)試。
[root@web1 ~]
停止 httpd: [確定]
|

注,大家可以看到,現(xiàn)在只能訪(fǎng)問(wèn)Web2,再重新啟動(dòng)Web1,再次訪(fǎng)問(wèn)一下。
1 2 | [root@web1 ~]
正在啟動(dòng) httpd: [確定]
|


注,大家可以看到,現(xiàn)在又可以重新訪(fǎng)問(wèn),說(shuō)明nginx的健康狀態(tài)查檢配置成功。但大家想一下,如果不幸的是所有服務(wù)器都不能提供服務(wù)了怎么辦,用戶(hù)打開(kāi)頁(yè)面就會(huì)出現(xiàn)出錯(cuò)頁(yè)面,那么會(huì)帶來(lái)用戶(hù)體驗(yàn)的降低,所以我們能不能像配置LVS是配置sorry_server呢,答案是可以的,但這里不是配置sorry_server而是配置backup。
12.配置backup服務(wù)器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [root@nginx ~]
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 ~]
[root@nginx errorpage]
<h1>Sorry......< /h1 >
|
13.重新加載配置文件
1 2 3 4 | [root@nginx errorpage]
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
14.關(guān)閉Web服務(wù)器并進(jìn)行測(cè)試
1 2 3 4 | [root@web1 ~]
停止 httpd: [確定]
[root@web2 ~]
停止 httpd: [確定]
|

注,大家可以看到,當(dāng)所有服務(wù)器都不能工作時(shí),就會(huì)啟動(dòng)備份服務(wù)器。好了,backup服務(wù)器就配置到這里,下面我們來(lái)配置ip_hash負(fù)載均衡。
15.配置ip_hash負(fù)載均衡
1 2 3 4 5 6 7 | [root@nginx ~]
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;
}
|
注,當(dāng)負(fù)載調(diào)度算法為ip_hash時(shí),后端服務(wù)器在負(fù)載均衡調(diào)度中的狀態(tài)不能有backup。(有人可能會(huì)問(wèn),為什么呢?大家想啊,如果負(fù)載均衡把你分配到backup服務(wù)器上,你能訪(fǎng)問(wèn)到頁(yè)面嗎?不能,所以了不能配置backup服務(wù)器)
16.重新加載一下服務(wù)器
1 2 3 4 | [root@nginx ~]
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
17.測(cè)試一下

注,大家可以看到,你不斷的刷新頁(yè)面一直會(huì)顯示的民Web2,說(shuō)明ip_hash負(fù)載均衡配置成功。下面我們來(lái)統(tǒng)計(jì)一下Web2的訪(fǎng)問(wèn)連接數(shù)。
18.統(tǒng)計(jì)Web2的訪(fǎng)問(wèn)連接數(shù)
注,你不斷的刷新,連接數(shù)會(huì)越來(lái)越多。好了,nginx的負(fù)載均衡就全部演示到這里下面我們來(lái)說(shuō)一說(shuō),頁(yè)面緩存。
六、Nginx之頁(yè)面緩存
1.指令說(shuō)明
語(yǔ)法:proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time] [max_size=size];
默認(rèn)值:None
使用字段:http
指令指定緩存的路徑和一些其他參數(shù),緩存的數(shù)據(jù)存儲(chǔ)在文件中,并且使用代理url的哈希值作為關(guān)鍵字與文件名。levels參數(shù)指定緩存的子目錄數(shù),例如:
1 | proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;
|
文件名類(lèi)似于:
1 | /data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
|
levels指定目錄結(jié)構(gòu),可以使用任意的1位或2位數(shù)字作為目錄結(jié)構(gòu),如 X, X:X,或X:X:X 例如: “2”, “2:2”, “1:1:2“,但是最多只能是三級(jí)目錄。
所有活動(dòng)的key和元數(shù)據(jù)存儲(chǔ)在共享的內(nèi)存池中,這個(gè)區(qū)域用keys_zone參數(shù)指定。one指的是共享池的名稱(chēng),10m指的是共享池的大小。
注意每一個(gè)定義的內(nèi)存池必須是不重復(fù)的路徑,例如:
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參數(shù)指定的時(shí)間內(nèi)緩存的數(shù)據(jù)沒(méi)有被請(qǐng)求則被刪除,默認(rèn)inactive為10分鐘。一個(gè)名為cache manager的進(jìn)程控制磁盤(pán)的緩存大小,它被用來(lái)刪除不活動(dòng)的緩存和控制緩存大小,這些都在max_size參數(shù)中定義,當(dāng)目前緩存的值超出max_size指定的值之后,超過(guò)其大小后最少使用數(shù)據(jù)(LRU替換算法)將被刪除。內(nèi)存池的大小按照緩存頁(yè)面數(shù)的比例進(jìn)行設(shè)置,一個(gè)頁(yè)面(文件)的元數(shù)據(jù)大小按照操作系統(tǒng)來(lái)定,如FreeBSD/i386下為64字節(jié),F(xiàn)reeBSD/amd64下為128字節(jié)。
語(yǔ)法:proxy_cache zone_name;
默認(rèn)值:None
使用字段:http, server, location
設(shè)置一個(gè)緩存區(qū)域的名稱(chēng),一個(gè)相同的區(qū)域可以在不同的地方使用。
在0.7.48后,緩存遵循后端的”Expires”, “Cache-Control: no-cache”, “Cache-Control: max-age=XXX”頭部字段,0.7.66版本以后,”Cache-Control:“private”和”no-store”頭同樣被遵循。nginx在緩存過(guò)程中不會(huì)處理”Vary”頭,為了確保一些私有數(shù)據(jù)不被所有的用戶(hù)看到,后端必須設(shè)置 “no-cache”或者”max-age=0”頭,或者proxy_cache_key包含用戶(hù)指定的數(shù)據(jù)如$cookie_xxx,使用cookie的值作為proxy_cache_key的一部分可以防止緩存私有數(shù)據(jù),所以可以在不同的location中分別指定proxy_cache_key的值以便分開(kāi)私有數(shù)據(jù)和公有數(shù)據(jù)。
緩存指令依賴(lài)代理緩沖區(qū)(buffers),如果proxy_buffers設(shè)置為off,緩存不會(huì)生效。
語(yǔ)法:proxy_cache_valid reply_code [reply_code …] time;
默認(rèn)值:None
使用字段:http, server, location
為不同的應(yīng)答設(shè)置不同的緩存時(shí)間,例如:
1 2 | proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
|
為應(yīng)答代碼為200和302的設(shè)置緩存時(shí)間為10分鐘,404代碼緩存1分鐘。
如果只定義時(shí)間:
那么只對(duì)代碼為200, 301和302的應(yīng)答進(jìn)行緩存。
同樣可以使用any參數(shù)任何應(yīng)答。
1 2 3 | proxy_cache_valid 200 302 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid any 1m;
|
2.定義一個(gè)簡(jiǎn)單nginx緩存服務(wù)器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [root@nginx ~]
proxy_cache_path /data/nginx/cache/webserver levels=1:2 keys_zone=webserver:20m max_size=1g;
server {
listen 80;
server_name localhost;
location / {
proxy_pass http: //webservers ;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache webserver;
proxy_cache_valid 200 10m;
}
}
|
3.新建緩存目錄
4.重新加載一下配置文件
1 2 3 4 | [root@nginx webserver]
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
5.下面我們來(lái)測(cè)試一下(谷歌瀏覽器)

注,大家用谷歌瀏覽器測(cè)試的時(shí)候,可以按F12調(diào)用開(kāi)發(fā)工具,選擇Network選項(xiàng),我們可以看到,Response Headers,在這里我們可以看到,我們請(qǐng)求的是否是緩存,但現(xiàn)在還看不到,下面我們來(lái)配置一下,再來(lái)測(cè)試。
6. 緩存變量說(shuō)明
服務(wù)器地址,在完成一次系統(tǒng)調(diào)用后可以確定這個(gè)值,如果要繞開(kāi)系統(tǒng)調(diào)用,則必須在listen中指定地址并且使用bind參數(shù)。
0.8.3版本中其值可能為:
MISS 未命中
EXPIRED - expired。請(qǐng)求被傳送到后端。
UPDATING - expired。由于proxy/fastcgi_cache_use_stale正在更新,將使用舊的應(yīng)答。
STALE - expired。由于proxy/fastcgi_cache_use_stale,后端將得到過(guò)期的應(yīng)答。
HIT 命中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [root@nginx ~]
proxy_cache_path /data/nginx/cache/webserver levels=1:2 keys_zone=webserver:20m max_size=1g;
server {
listen 80;
server_name localhost;
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 ~]
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
8.測(cè)試一下

注,從圖中我們可以看到,我們?cè)L問(wèn)的服務(wù)器是192.168.18.208,緩存命中。大家可以看到是不是很直觀(guān)啊。下面我們看一下緩存目錄。
9.查看一下緩存目錄
1 2 3 | [root@nginx ~]
[root@nginx 63]
681ad4c77694b65d61c9985553a2763f
|
注,緩存目錄里確實(shí)有緩存文件。好了,nginx緩存配置就到這邊了,更多配置請(qǐng)根據(jù)需要看配置文檔。下面我們來(lái)說(shuō)一下,URL重寫(xiě)。
七、Nginx之URL重寫(xiě)
摘要
這個(gè)模塊允許使用正則表達(dá)式重寫(xiě)URI(需PCRE庫(kù)),并且可以根據(jù)相關(guān)變量重定向和選擇不同的配置。如果這個(gè)指令在server字段中指定,那么將在被請(qǐng)求的location確定之前執(zhí)行,如果在指令執(zhí)行后所選擇的location中有其他的重寫(xiě)規(guī)則,那么它們也被執(zhí)行。如果在location中執(zhí)行這個(gè)指令產(chǎn)生了新的URI,那么location又一次確定了新的URI。這樣的循環(huán)可以最多執(zhí)行10次,超過(guò)以后nginx將返回500錯(cuò)誤。
語(yǔ)法:break
默認(rèn)值:none
使用字段:server, location, if
完成當(dāng)前設(shè)置的規(guī)則,停止執(zhí)行其他的重寫(xiě)指令。
示例:
1 2 3 4 | if ($slow) {
limit_rate 10k;
break ;
}
|
語(yǔ)法:if (condition) { … }
默認(rèn)值:none
使用字段:server, location
注意:在使用if指令之前請(qǐng)查看if is evil page并且盡量考慮用try_files代替。
判斷一個(gè)條件,如果條件成立,則后面的大括號(hào)內(nèi)的語(yǔ)句將執(zhí)行,相關(guān)配置從上級(jí)繼承。
可以在判斷語(yǔ)句中指定下列值:
一個(gè)變量的名稱(chēng);不成立的值為:空字符傳”“或者一些用“0”開(kāi)始的字符串。
一個(gè)使用=或者!=運(yùn)算符的比較語(yǔ)句。
使用符號(hào)~*和~模式匹配的正則表達(dá)式:
~為區(qū)分大小寫(xiě)的匹配。
~*不區(qū)分大小寫(xiě)的匹配(firefox匹配FireFox)。
!~和!~*意為“不匹配的”。
使用-f和!-f檢查一個(gè)文件是否存在。
使用-d和!-d檢查一個(gè)目錄是否存在。
使用-e和!-e檢查一個(gè)文件,目錄或者軟鏈接是否存在。
使用-x和!-x檢查一個(gè)文件是否為可執(zhí)行文件。
正則表達(dá)式的一部分可以用圓括號(hào),方便之后按照順序用$1-$9來(lái)引用。
示例配置:
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;
}
|
內(nèi)置變量$invalid_referer用指令valid_referers指定。
語(yǔ)法:return code
默認(rèn)值:none
使用字段:server, location, if
這個(gè)指令結(jié)束執(zhí)行配置語(yǔ)句并為客戶(hù)端返回狀態(tài)代碼,可以使用下列的值:204,400,402-406,408,410, 411, 413, 416與500-504。此外,非標(biāo)準(zhǔn)代碼444將關(guān)閉連接并且不發(fā)送任何的頭部。
語(yǔ)法:rewrite regex replacement flag
默認(rèn)值:none
使用字段:server, location, if
按照相關(guān)的正則表達(dá)式與字符串修改URI,指令按照在配置文件中出現(xiàn)的順序執(zhí)行。
可以在重寫(xiě)指令后面添加標(biāo)記。
如果替換的字符串以http://開(kāi)頭,請(qǐng)求將被重定向,并且不再執(zhí)行多余的rewrite指令。
尾部的標(biāo)記(flag)可以是以下的值:
注意如果一個(gè)重定向是相對(duì)的(沒(méi)有主機(jī)名部分),nginx將在重定向的過(guò)程中使用匹配server_name指令的“Host”頭或者server_name指令指定的第一個(gè)名稱(chēng),如果頭不匹配或不存在,如果沒(méi)有設(shè)置server_name,將使用本地主機(jī)名,如果你總是想讓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;
|
但是如果我們將其放入一個(gè)名為/download/的location中,則需要將last標(biāo)記改為break,否則nginx將執(zhí)行10次循環(huán)并返回500錯(cuò)誤。
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;
}
|
如果替換字段中包含參數(shù),那么其余的請(qǐng)求參數(shù)將附加到后面,為了防止附加,可以在最后一個(gè)字符后面跟一個(gè)問(wèn)號(hào):
1 | rewrite ^ /users/ (.*)$ /show ?user=$1? last;
|
注意:大括號(hào)({和}),可以同時(shí)用在正則表達(dá)式和配置塊中,為了防止沖突,正則表達(dá)式使用大括號(hào)需要用雙引號(hào)(或者單引號(hào))。例如要重寫(xiě)以下的URL:
為:
1 | /path/to/photos/12/1234/123456 .png
|
則使用以下正則表達(dá)式(注意引號(hào)):
1 | rewrite "/photos/([0-9] {2})([0-9] {2})([0-9] {2})" /path/to/photos/ $1/$1$2/$1$2$3.png;
|
如果指定一個(gè)“?”在重寫(xiě)的結(jié)尾,Nginx將丟棄請(qǐng)求中的參數(shù),即變量$args,當(dāng)使用$request_uri或$uri&$args時(shí)可以在rewrite結(jié)尾使用“?”以避免nginx處理兩次參數(shù)串。
在rewrite中使用$request_uri將www.example.com重寫(xiě)到example.com:
1 2 3 4 | server {
server_name www.example.com;
rewrite ^ http: //example .com$request_uri? permanent;
}
|
同樣,重寫(xiě)只對(duì)路徑進(jìn)行操作,而不是參數(shù),如果要重寫(xiě)一個(gè)帶參數(shù)的URL,可以使用以下代替:
1 2 3 | if ($args ^~ post=100){
rewrite ^ http: //example .com /new-address .html? permanent;
}
|
注意$args變量不會(huì)被編譯,與location過(guò)程中的URI不同(參考http核心模塊中的location)。
語(yǔ)法:rewrite_log on | off
默認(rèn)值:rewrite_log off
使用字段:server, location, if
變量:無(wú)
啟用時(shí)將在error log中記錄notice 標(biāo)記的重寫(xiě)日志。
語(yǔ)法:set variable value
默認(rèn)值:none
使用字段:server, location, if
指令設(shè)置一個(gè)變量并為其賦值,其值可以是文本,變量和它們的組合。
你可以使用set定義一個(gè)新的變量,但是不能使用set設(shè)置$http_xxx頭部變量的值。
語(yǔ)法:uninitialized_variable_warn on|off
默認(rèn)值:uninitialized_variable_warn on
使用字段:http, server, location, if
開(kāi)啟或關(guān)閉在未初始化變量中記錄警告日志。
事實(shí)上,rewrite指令在配置文件加載時(shí)已經(jīng)編譯到內(nèi)部代碼中,在解釋器產(chǎn)生請(qǐng)求時(shí)使用。
這個(gè)解釋器是一個(gè)簡(jiǎn)單的堆棧虛擬機(jī),如下列指令:
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
|
注意并沒(méi)有關(guān)于limit_rate的代碼,因?yàn)樗鼪](méi)有提及ngx_http_rewrite_module模塊,“if”塊可以類(lèi)似”location”指令在配置文件的相同部分同時(shí)存在。
如果$slow為真,對(duì)應(yīng)的if塊將生效,在這個(gè)配置中l(wèi)imit_rate的值為10k。
指令:
1 | rewrite ^/(download/.*) /media/ (.*)\..*$ /$1 /mp3/ $2.mp3 break ;
|
如果我們將第一個(gè)斜杠括入圓括號(hào),則可以減少執(zhí)行順序:
1 | rewrite ^( /download/ .*) /media/ (.*)\..*$ $1 /mp3/ $2.mp3 break ;
|
之后的順序類(lèi)似如下:
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.簡(jiǎn)單案例
注,由于配置文件內(nèi)容較多,為了讓大家看著方便,我們備份一下配置文件,打開(kāi)一個(gè)新的配置文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [root@nginx ~]
[root@nginx nginx]
[root@nginx nginx]
[root@nginx nginx]
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
rewrite ^ /bbs/ (.*)$ http: //192 .168.18.201 /forum/ $1;
}
}
|
準(zhǔn)備forum目錄與測(cè)試文件
1 2 3 4 5 6 7 | [root@web1 ~]
[root@web1 html]
index.html
[root@web1 html]
[root@web1 html]
[root@web1 forum]
<h1>forum page!< /h1 >
|
測(cè)試一下

好了,下面我們來(lái)測(cè)試一下rewrite重寫(xiě)。
3.重新加載一下配置文件
1 2 3 4 | [root@nginx 63]
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
4.測(cè)試一下

注,大家可以從圖中看出,status code 302指的是臨時(shí)重定向,那就說(shuō)明我們r(jià)ewrite重寫(xiě)配置成功。大家知道302是臨時(shí)重定向而301是永久重定向,那么怎么實(shí)現(xiàn)永久重定向呢。一般服務(wù)器與服務(wù)器之間是臨時(shí)重定向,服務(wù)器內(nèi)部是永久重定向。下面我們來(lái)演示一下永久重定向。
5.配置永久重定向
1 2 3 4 5 6 7 8 9 10 11 12 | [root@nginx nginx]
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
rewrite ^ /bbs/ (.*)$ /forum/ $1;
}
}
|
準(zhǔn)備forum目錄與測(cè)試文件
1 2 3 4 5 6 7 | [root@nginx ~]
[root@nginx html]
50x.html index.html
[root@nginx html]
[root@nginx html]
[root@nginx forum]
<h1>192.168.18.208 forum page< /h1 >
|
6.重新加載一下配置文件
1 2 3 4 | [root@nginx ~]
nginx: the configuration file /etc/nginx/nginx .conf syntax is ok
nginx: configuration file /etc/nginx/nginx .conf test is successful
重新載入 nginx: [確定]
|
7.測(cè)試一下

注,大家從圖中可以看到,我們?cè)L問(wèn)bbs/是直接幫我們跳轉(zhuǎn)到forum/下,這種本機(jī)的跳轉(zhuǎn)就是永久重定向也叫隱式重定向。好了,rewrite重定向我們就說(shuō)到這里了,想要查詢(xún)更多關(guān)于重定向的指令請(qǐng)參考官方文檔。最后,我們來(lái)說(shuō)一下讀寫(xiě)分離。
八、Nginx之讀寫(xiě)分離
1.實(shí)驗(yàn)拓?fù)?/span>

需求分析,前端一臺(tái)nginx做負(fù)載均衡反向代理,后面兩臺(tái)httpd服務(wù)器。整個(gè)架構(gòu)是提供BBS(論壇)服務(wù),有一需求得實(shí)現(xiàn)讀寫(xiě)分離,就是上傳附件的功能,我們上傳的附件只能上傳到Web1,然后在Web1上利用rsync+inotify實(shí)現(xiàn)附件同步,大家都知道rsync+inotify只能是主向從同步,不能雙向同步。所以Web1可進(jìn)行寫(xiě)操作,而Web2只能進(jìn)行讀操作,這就帶來(lái)讀寫(xiě)分離的需求,下面我們就來(lái)說(shuō)一下,讀寫(xiě)分離怎么實(shí)現(xiàn)。
2.WebDAV功能說(shuō)明
WebDAV (Web-based Distributed Authoring and Versioning) 一種基于 HTTP 1.1協(xié)議的通信協(xié)議。它擴(kuò)展了HTTP 1.1,在GET、POST、HEAD等幾個(gè)HTTP標(biāo)準(zhǔn)方法以外添加了一些新的方法,使應(yīng)用程序可直接對(duì)Web Server直接讀寫(xiě),并支持寫(xiě)文件鎖定(Locking)及解鎖(Unlock),還可以支持文件的版本控制。這樣我們就能配置讀寫(xiě)分離功能了,下面我們來(lái)具體配置一下。
3.修改配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 | [root@nginx nginx]
server {
listen 80;
server_name localhost;
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 ~]
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功能

注,在<Directory "/var/www/html">下啟用就行。
6.重新啟動(dòng)一下httpd
1 2 3 | [root@web1 ~]
停止 httpd: [確定]
正在啟動(dòng) httpd: [確定]
|
7.測(cè)試一下
1 2 3 4 | [root@nginx ~]
<h1>web1. test .com< /h1 >
[root@nginx ~]
<h1>web2. test .com< /h1 >
|
注,web1與web2訪(fǎng)問(wèn)都沒(méi)問(wèn)題。
1 2 3 4 5 6 7 8 9 10 | [root@nginx ~]
<!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上時(shí),因?yàn)閣eb2只人讀功能,所以沒(méi)有開(kāi)戶(hù)WebDAV功能,所以顯示是405 Method Not Allowed。
1 2 3 4 5 6 7 8 9 10 11 | [root@nginx ~]
<!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 >
|
注,我們?cè)赪eb1開(kāi)啟了WebDAV功能,但我們目錄是root目錄是不允許apache用戶(hù)上傳的,所以顯示的是403 Forbidden。下面我們給apache授權(quán),允許上傳。
下面我們?cè)賮?lái)測(cè)試一下,
1 2 3 4 5 6 7 8 9 10 | [root@nginx ~]
<!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 >
|
注,大家可以看到我們成功的上傳了文件,說(shuō)明nginx讀寫(xiě)分離功能配置完成。最后,我們來(lái)查看一下上傳的文件。
1 2 3 4 5 6 | [root@web1 ~]
[root@web1 html]
總用量 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的反向代理、負(fù)載均衡、頁(yè)面緩存、URL重寫(xiě)及讀寫(xiě)分離就全部講解完成。希望大家有所收獲,^_^……
本文出自 “Share your knowledge …” 博客,請(qǐng)務(wù)必保留此出處http://freeloda.blog.51cto.com/2033581/1288553