Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解(1)
大綱
一、前言
二、環境準備
三、安裝與配置Nginx
四、Nginx之反向代理
五、Nginx之負載均衡
六、Nginx之頁面緩存
七、Nginx之URL重寫
八、Nginx之讀寫分離
注,操作系統為 CentOS 6.4 x86_64 , Nginx 是版本是最新版的1.4.2,所以實驗用到的軟件請點擊這里下載:http://yunpan.cn/QXIgqMmVmuZrm
一、前言
? ? ? ?在前面的幾篇博文中我們主要講解了Nginx作為Web服務器知識點,主要的知識點有nginx的理論詳解、nginx作為web服務器的操作講解、 nginx作為LNMP架構的講解,不清楚的博友可以回頭看看,在這一篇博客中我們主要講解, nginx的反向代理、負載均衡、緩存、URL重寫以及讀寫分離詳解。好了,下面我們來具體說一說。
二、環境準備
1. 操作系統
CentOS 6.4 x86_64
2.軟件版本
Nginx 1.4.2
3.實驗拓撲
注,實驗拓撲見下文。
4.安裝yum源
[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.各節點時間同步
[root@nginx ~]# ntpdate 202.120.2.101
[root@web1 ~]# ntpdate 202.120.2.101
[root@web2 ~]# ntpdate 202.120.2.101
6.關閉防火墻與SELinux
[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.解壓
[root@nginx src]# tar xf nginx-1.4.2.tar.gz
2.新建nginx用戶與組
[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.準備編譯配置文件
[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.編譯并安裝
[root@nginx nginx-1.4.2]# make && make install
5.為nginx提供SysV init腳本
[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?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() {?
???# 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?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.為此腳本賦予執行權限
[root@nginx ~]# chmod +x /etc/init.d/nginx
7.添加至服務管理列表,并讓其開機自動啟動
[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
[root@nginx ~]# service nginx start
正在啟動 nginx:?????????????????????????????????????????? [確定]
9.查看一下端口
[root@nginx ~]# netstat -ntlp | grep :80
tcp??????? 0????? 0 0.0.0.0:80????????????????? 0.0.0.0:*?????????????????? LISTEN????? 3889/nginx
10.測試一下
好了,Nginx安裝與配置就到這里,下面我們來說一說Nginx的反向代理。
四、Nginx之反向代理
在配置nginx反向代理之間我們得先準備兩臺測試服務器,Web1與Web2。
1.安裝httpd
[root@web1 ~]# yum install -y httpd
[root@web2 ~]# yum install -y httpd
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服務
[root@web1 ~]# service httpd start
正在啟動 httpd:?????????????????????????????????????????? [確定]
[root@web2 ~]# service httpd start
正在啟動 httpd:?????????????????????????????????????????? [確定]
4.測試一下
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。 ? ??
如下例:
location / {
??proxy_pass??????? http://localhost:8000;
??proxy_set_header? X-Real-IP? $remote_addr;
}
注意,當使用http proxy模塊(甚至FastCGI),所有的連接請求在發送到后端服務器之前nginx將緩存它們,因此,在測量從后端傳送的數據時,它的進度顯示可能不正確。
實驗拓撲:
7.配置http反向代理
[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.重新加載一下配置文件
[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.測試一下
注,大家可以看到,當我們訪問192.168.18.208時,被代理重新定向到Web1上。
10.查看一下Web服務器日志
[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配置文件
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.重新加載一下配置文件
[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.測試并查看日志
[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
注,大家可以這里記錄日志的參數還是%h,下面我們修改一下參數。
注,這是修改后的參數,將h%修改為%{X-Real-IP}i,好的下面我們再來測試一下。
15.重啟并測試
[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代理后端一臺服務器就演示到這里,下面我們繼續說。
五、Nginx之負載均衡
注,大家可以看到,由于我們網站是發展初期,nginx只代理了后端一臺服務器,但由于我們網站名氣大漲訪問的人越來越多一臺服務器實在是頂不住,于是我們加了多臺服務器,那么多臺服務器又怎么配置代理呢,我們這里以兩臺服務器為案例,為大家做演示。
1.upstream 負載均衡模塊說明
案例:
下面設定負載均衡的服務器列表。
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.實驗拓撲
5.配置nginx負載均衡
[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.重新加載一下配置文件
[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.測試一下
注,大家可以不斷的刷新瀏覽的內容,可以發現web1與web2是交替出現的,達到了負載均衡的效果。
8.查看一下Web訪問服務器日志
Web1:
[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服務器記錄日志的格式。
[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:?????????????????????????????????????????? [確定]
接著,再訪問多次,繼續查看日志。
[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一起使用,進行健康狀態檢查。
[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.重新加載一下配置文件
[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.停止服務器并測試
先停止Web1,進行測試。
[root@web1 ~]# service httpd stop
停止 httpd:?????????????????????????????????????????????? [確定]
注,大家可以看到,現在只能訪問Web2,再重新啟動Web1,再次訪問一下。
[root@web1 ~]# service httpd start
正在啟動 httpd:?????????????????????????????????????????? [確定]
注, 大家可以看到,現在又可以重新訪問,說明nginx的健康狀態查檢配置成功。但大家想一下,如果不幸的是所有服務器都不能提供服務了怎么辦,用戶打開頁面 就會出現出錯頁面,那么會帶來用戶體驗的降低,所以我們能不能像配置LVS是配置sorry_server呢,答案是可以的,但這里不是配置 sorry_server而是配置backup。
12.配置backup服務器
[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.重新加載配置文件
[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服務器并進行測試
[root@web1 ~]# service httpd stop
停止 httpd:?????????????????????????????????????????????? [確定]
[root@web2 ~]# service httpd stop
停止 httpd:?????????????????????????????????????????????? [確定]
注,大家可以看到,當所有服務器都不能工作時,就會啟動備份服務器。好了,backup服務器就配置到這里,下面我們來配置ip_hash負載均衡。
15.配置ip_hash負載均衡
ip_hash,每個請求按訪問IP的hash結果分配,這樣來自同一個IP的訪客固定訪問一個后端服務器,有效解決了動態網頁存在的session共享問題。(一般電子商務網站用的比較多)
[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.重新加載一下服務器
[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.測試一下
注,大家可以看到,你不斷的刷新頁面一直會顯示的民Web2,說明ip_hash負載均衡配置成功。下面我們來統計一下Web2的訪問連接數。
18.統計Web2的訪問連接數
[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的哈希值作為關鍵字與文件名。levels參數指定緩存的子目錄數,例如:
proxy_cache_path??/data/nginx/cache??levels=1:2?? keys_zone=one:10m;
文件名類似于:
/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指的是共享池的大小。 ?
注意每一個定義的內存池必須是不重復的路徑,例如:
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 ?
為不同的應答設置不同的緩存時間,例如:
proxy_cache_valid? 200 302? 10m;
proxy_cache_valid? 404????? 1m;
為應答代碼為200和302的設置緩存時間為10分鐘,404代碼緩存1分鐘。 ?
如果只定義時間:
proxy_cache_valid 5m;
那么只對代碼為200, 301和302的應答進行緩存。 ?
同樣可以使用any參數任何應答。
proxy_cache_valid? 200 302 10m;
proxy_cache_valid? 301 1h;
proxy_cache_valid? any 1m;
2.定義一個簡單nginx緩存服務器
[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.新建緩存目錄
[root@nginx ~]# mkdir -pv /data/nginx/cache/webserver
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.下面我們來測試一下(谷歌瀏覽器)
注,大家用谷歌瀏覽器測試的時候,可以按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 命中
[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.重新加載一下配置文件
[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.測試一下
注,從圖中我們可以看到,我們訪問的服務器是192.168.18.208,緩存命中。大家可以看到是不是很直觀啊。下面我們看一下緩存目錄。
9.查看一下緩存目錄
[root@nginx ~]# cd /data/nginx/cache/webserver/f/63/
[root@nginx 63]# ls
681ad4c77694b65d61c9985553a2763f
注,緩存目錄里確實有緩存文件。好了,nginx緩存配置就到這邊了,更多配置請根據需要看配置文檔。下面我們來說一下,URL重寫。
轉載于:https://blog.51cto.com/tianshili/1640084
總結
以上是生活随笔為你收集整理的Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bash脚本编程之一 条件判断及算术运算
- 下一篇: Nginx基础入门之nginx基础配置项