目錄
<a>1、nginx軟體安裝</a>
<a>2、nginx proxy負載均衡搭建過程</a>
<a>3、不同域名站點分離</a>
<a>4、WEB日志用戶端IP記錄</a>
<a>5、根據擴充名實作伺服器的動靜分離</a>
<a>6、http proxy參數</a>
<a>7、Location指令</a>
<a>8、upstream參數</a>
<a>9、nginx負載均衡排程算法</a>
#####################################################
本文内容來自《老男孩linux運維實戰教育訓練》學生—MR楊
歡迎廣大運維同仁一起交流linux/unix網站運維技術!
QQ:10286460
E-mail:[email protected]
1.1硬體準備
4台虛拟機,一台做負載均衡,兩台做RS,一台做用戶端
hostname
IP
功能
nginx-1
10.0.0.239
nginx代理與負載均衡伺服器
RS1
10.0.0.237
真實WEB伺服器
RS2
10.0.0.240
Client
10.0.0.238
用戶端
1.2軟體準備
centos 5.8 x86_64
nginx-1.2.3.tar.gz
pcre-8.30.tar.gz
1.3下載下傳位址
wgethttp://nginx.org/download/nginx-1.2.9.tar.gz
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.30.tar.gz
我使用的源包目錄為/usr/local/src/
1.4安裝pcre
tar zxf pcre-8.30.tar.gz
cd pcre-8.30/
./configure
make && make install
cd ../
安裝pcre庫是為了相容nginx rewrite
1.5安裝nginx
useradd nginx -M -s /sbin/nologin
tar -zxf nginx-1.2.9.tar.gz
cd nginx-1.2.9
./configure --user=nginx --group=nginx --prefix=/application/nginx-1.2.9 --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module
安裝完成後,檢查文法,發現有錯誤!
[root@nginx-1 nginx-1.2.9]# /application/nginx-1.2.9/sbin/nginx -t
/application/nginx-1.2.9/sbin/nginx: error while loading sharedlibraries: libpcre.so.1: cannot open shared object file: No such file ordirectory
[root@nginx-1 nginx-1.2.9]#echo "/usr/local/lib" >>/etc/ld.so.conf #配置lib庫,解決上述錯誤
[root@nginx-1 nginx-1.2.9]#ldconfig #使ld.so.conf修改生效
[root@nginx-1 nginx-1.2.9]#/application/nginx-1.2.9/sbin/nginx -t#檢查文法,成功!
nginx: the configuration file/application/nginx-1.2.9/conf/nginx.conf syntax is ok
nginx: configuration file/application/nginx-1.2.9/conf/nginx.conf test is successful
[root@nginx-1 nginx-1.2.9]#ln -s /application/nginx-1.2.9 /application/nginx #增加軟連結,友善更新
[root@nginx-1 nginx-1.2.9]#ll -d /application/nginx #檢視軟連結是否成功,如果閃動就沒成功
lrwxrwxrwx 1 root root 24 Sep 8 18:42 /application/nginx ->/application/nginx-1.2.9
[root@nginx-1 nginx-1.2.9]# echo 'export PATH=$PATH:/application/nginx/sbin' >>/etc/profile#将Nginx指令加入系統全局變量,啟動nginx
[root@nginx-1 nginx-1.2.9]#source /etc/profile #使全局變量修改生效
[root@nginx-1 nginx-1.2.9]#nginx #啟動nginx
[root@nginx-1 nginx-1.2.9]#echo'/application/nginx/sbin/nginx' >> /etc/rc.local #加入開機自啟動
[[email protected]]#netstat -plnt |grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1352/nginx
1.6測試:
<a href="http://blog.51cto.com/attachment/201309/235635903.jpg" target="_blank"></a>
2.1nginx proxy配置
把下面内容添加到nginx.conf中,位置在最後一個大括号的前面。
upstream webserver {
server 10.0.0.240:80 weight=3;
server 10.0.0.237:80 weight=3;
}
server {
listen 80;
server_name www.etiantian.org;
location / {
proxy_pass http://webserver;
參數解釋:
upstream webserver { } 定義真實伺服器組
server {} 定義一個服務配置
listen 80 監聽80端口
server_name 監聽的位址或IP
location / 比對server_name後的url或IP
proxy_pass 代理參數,後接upstream定義的伺服器組
注:nginx proxy預設使用的是rr算法
修改完後,檢查文法重新開機
[root@nginx-1 conf]# nginx -t
nginx: the configuration file /application/nginx-1.2.9/conf/nginx.confsyntax is ok
[root@nginx-1 conf]# nginx -s reload
2.2真實伺服器配置
兩台操作一樣,不需要動nginx.conf配置檔案
[root@RS2 nginx]# echo 240-www >/application/nginx/html/index.html
[root@RS1 nginx]# echo 237-www >/application/nginx/html/index.html
2.3用戶端測試:
[root@Client ~]# echo "10.0.0.239 www.etiantian.org" >>/etc/hosts
[root@Client~]# curl www.etiantian.org
240-www
[root@Client ~]# curl www.etiantian.org
237-www
目前已經可以進行負載均衡,但還存在一些問題。
2.4問題描述1:
通路blog與bbs時,請求沒有轉發到真實伺服器,而傳回是的代理伺服器本地的web内容
複現問題:
2.4.1在真實伺服器上配置建立blog,bbs站點目錄
[root@RS2 nginx]# mkdir/data/html/blog -p
[root@RS2 nginx]# mkdir/data/html/bbs -p
[root@RS2 nginx]# echo240-blog > /data/html/blog/index.html
[root@RS2 nginx]# echo240-bbs > /data/html/bbs/index.html
2.4.2新增站點配置
把下面内容添加到240的nginx.conf中,位置在最後一個大括号前
server_name blog.etiantian.org; #指定比對域名
root /data/html/blog; #指定站點目錄
index index.html index.htm;
server_name bbs.etiantian.org; #指定比對域名
root /data/html/bbs; #指定站點目錄
配置完後檢查文法重新開機
[root@RS2 nginx]#/application/nginx/sbin/nginx -t
[root@RS2 nginx]# /application/nginx/sbin/nginx-s reload
2.4.3用戶端測試
修改hosts解析檔案如下
[root@Client ~]# tail -1 /etc/hosts
10.0.0.239 www.etiantian.org blog.etiantian.org bbs.etiantian.org
測試:
[root@Client ~]# curl bbs.etiantian.org
239-www
[root@Client ~]# curl blog.etiantian.org
可以看出上面傳回的都是nginx proxy本地的資料
2.4.4找到問題:
檢視nginx proxy的配置檔案,發現隻有比對www.etiantian.org的會被代理到webserver組中的位址,其它的都比對上localhost;通路本地的web站點(下面紅色顯示)。
[root@nginx-1 conf]# grep -v "#"nginx.conf
worker_processes 1;
events {
worker_connections 1024;
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server_name localhost;
root html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
2.4.5解決方法
1)修改nginx proxy配置檔案:
3)把上面紅色字型的server定義注釋,本地不需要提供服務,隻留下代理配置就OK
修改後的配置如下:
server_name localhost;
[root@nginx-1 conf]# nginx -t #檢查文法
繼續在用戶端測試
可看出上面請求已經轉發到真實伺服器上去了。因為localhost是指的本機IP,隻要目的IP是本機端口80的就代理到真實伺服器上。
上步測試為什麼都是www站點?
3.1直接通路測試
修改hosts檔案,直接通路是正常的
10.0.0.240 www.etiantian.org blog.etiantian.org bbs.etiantian.org
240-bbs
240-blog
直接通路結果是正确的,但為什麼通過nginx代理過去的請求,不能區分blog,bbs,www站點呢?原因是:nginx代理轉發請求的時候,不攜帶原始url内容,是以比對預設www站點了。
3.2添加proxy_set_header參數
修改nginx代理上的nginx.conf檔案,在proxy_pass下添加紅色内容
[root@nginx-1 conf]# grep -v "#" nginx.conf|grep proxy
proxy_set_header Host $host;
/application/nginx/sbin/nginx -t
/application/nginx/sbin/nginx -s reload
3.3用戶端測試:
237-bbs
通路已經正常!
4.1日志檢視
日志路徑在/application/nginx/logs/下
[root@RS2 nginx]# tail -1 logs/access.log
10.0.0.239 - - [09/Sep/2013:19:48:16 +0800]"GET / HTTP/1.0" 200 9 "-" "curl/7.15.5(x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3libidn/0.6.5"
發現隻記錄了nginx代理的位址,沒有客戶機的位址,不友善統計客戶IP通路次數!
4.2在nginx proxy配置檔案添加X-Forwarded-For參數
在nginx proxy伺服器nginx.conf裡添加紅色參數
[root@nginx-1 nginx]# grep -v "#"conf/nginx.conf|grep proxy
proxy_set_header X-Forwarded-For $remote_addr;
注:X-Forwarded-For(XFF)是用來識别通過HTTP代理或負載均衡方式連接配接到Web伺服器的用戶端最原始的IP位址的HTTP請求頭字段。
4.3修改真實伺服器的nginx.conf上修改日志參數
log_format main '$remote_addr - $remote_user[$time_local] "$request" '
'$status $body_bytes_sent"$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" ';
access_log logs/access.log main;
取消上面内容前面的#号,不然系統還會按預設的日志格式輸出
檢查文法并重新開機,隻要修改了配置檔案,就需要重新開機服務
4.4日志WEBIP測試:
[root@RS2 nginx]# tail logs/access.log
10.0.0.239 - - [09/Sep/2013:20:32:11 +0800]"GET / HTTP/1.0" 200 8 "-" "curl/7.15.5(x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3libidn/0.6.5"
10.0.0.239 - - [09/Sep/2013:20:33:01 +0800]"GET / HTTP/1.0" 200 8 "-" "curl/7.15.5(x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3libidn/0.6.5"
10.0.0.239 - - [09/Sep/2013:20:35:51 +0800]"GET / HTTP/1.0" 200 8 "-" "curl/7.15.5(x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3libidn/0.6.5" "10.0.0.238"
已經在日志中加入了真實用戶端位址!
模拟RS1為圖檔存儲伺服器,RS2為動态内容存儲伺服器,以bbs域名舉例
修改nginx proxy上面配置,添加下列配置(紅色部分)
upstream static_pools {
upstream dynamic_pools {
server_name blog.etiantian.org;
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
proxy_pass http://static_pools;
include proxy.conf;
location ~ .*\.(php|php3|php5)$ {
proxy_pass http://dynamic_pools;
include proxy.conf; #當參數比較多,且參數相同時,可使用包含檔案功能,使配置檔案顯得簡潔,該路徑配置使用相對路徑
#server {
#listen 80;
#server_name blog.etiantian.org;
#location / {
#proxy_pass http://webserver;
#proxy_set_header Host $host;
#proxy_set_header X-Forwarded-For $remote_addr;
#}
proxy.conf檔案裡參數配置
[root@nginx-1 conf]# vi /application/nginx/conf/proxy.conf
client_max_body_size 300m;
client_body_buffer_size 128k;
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_buffer_size 16k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
#允許用戶端請求的最大的單個檔案位元組數
client_max_body_size 300m;
#緩沖區代理緩沖使用者端請求的最大位元組數可以了解為先儲存到本地再傳給使用者
client_body_buffer_size 128k;
#跟後端伺服器連接配接的逾時時間_發起握手等候響應逾時時間
proxy_connect_timeout 600;
#連接配接成功後_等候後端伺服器響應時間_其實已經進入後端的排隊之中等候處理
proxy_read_timeout 600;
#後端伺服器資料回傳時間_就是在規定時間之内後端伺服器必須傳完所有的資料
proxy_send_timeout 600;
#代理請求緩存區_這個緩存區間會儲存使用者的頭資訊以供Nginx進行規則處理_一般隻要能儲存下頭資訊即可
proxy_buffer_size 16k;
#同上告訴Nginx儲存單個用的幾個Buffer 最大用多大空間
proxy_buffers 4 32k;
#如果系統很忙的時候可以申請更大的proxy_buffers 官方推薦*2
#擷取url頭部資訊,用于真實伺服器區分域名
proxy_set_header Host$host;
#用于真實伺服器擷取用戶端IP資訊
proxy_set_headerX-Forwarded-For $remote_addr;
模拟動态靜态伺服器
1)檢視blog站點目錄
[root@RS2 conf]# cat /application/nginx/conf/nginx.conf|grep bbs
server_name bbs.etiantian.org;
root /data/html/bbs;
#RS1路徑也一樣
2)模拟動态和靜态站點目錄下檔案
[root@RS2 conf]# mkdir /data/html/bbs/soft -p
[root@RS2 conf]# echo 240-static-blog> /data/html/bbs/soft/3011.jpg
#圖檔放在RS2上
[root@RS1 conf]# mkdir /data/html/bbs/soft -p
[root@RS1 conf]# echo 237-dynamic-blog> /data/html/bbs/soft/3011.php
#php檔案放在RS1上
3)用戶端測試
[root@Client ~]# tail -1/etc/hosts
10.0.0.239 www.etiantian.org blog.etiantian.org bbs.etiantian.org #bbs域名解析到nginx proxy上
[root@Client ~]# curl bbs.etiantian.org/soft/3011.jpg
240-static-blog
[root@Client ~]# curl bbs.etiantian.org/soft/3011.php
237-dynamic-bbs
#域名通路還是分擔的,但是對于.jpg或.php結尾的字尾,都會轉交到專門的伺服器上,由此就可以實作動靜分離。這是LVS不能實作的。
proxy_next_upstream
文法:proxy_next_upstream [error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off]
确定在何種情況下請求将轉發到下一個伺服器。轉發請求隻發生在沒有資料傳遞到用戶端的過程中。
proxy_connect_timeout
後端伺服器連接配接的逾時時間_發起握手等候響應逾時時間
proxy_read_timeout
連接配接成功後_等候後端伺服器響應時間_其實已經進入後端的排隊之中等候處理(也可以說是後端伺服器處理請求的時間)
proxy_send_timeout
後端伺服器資料回傳時間_就是在規定時間之内後端伺服器必須傳完所有的資料
proxy_pass
這個指令設定被代理伺服器的位址和被映射的URI
nginx均衡器轉發到真實伺服器時,不攜帶請求的url,設定該參數時,就會攜帶原始url
當服務端需要擷取客戶機ip時,需要加上該選項,會在通路日志中有客戶IP記錄
文法: location [=|~|~*|^~] /uri/ { …}
解釋:
=
精确比對,如果找到,立即停止搜尋,并立即處理請求(優先級最高)
^~
表示uri以某個正常字元串開頭,了解為比對url路徑即可。nginx不對url做編碼,是以請求為/static/20%/aa,可以被規則^~ /static/ /aa比對到(注意是空格)。
~
區分大小寫的正則比對
~*
不區分大小寫的正則比對
/
通用比對,任何請求都會比對到。
@
指定一個命名的location,一般隻用于内部重定向請求
比對順序
首先比對 =,其次比對^~, 其次是按檔案中順序的正則比對,最後是交給 / 通用比對。當有比對成功時候,停止比對,按目前比對規則處理請求。
每個裝置的狀态參數如下:
參數
描述
weight
預設為1,weight越大,負載的權重就越大
backup
熱備配置(RS高可用),目前面激活的RS都失敗後會自動啟用熱備RS
max_fails
最大嘗試失敗的次數,預設為1,0表示禁止償試。企業場景,2-3次比較合理。
fail_timeout
失敗逾時時間,預設是10s,正常業務2-3s比較合理
down
表示這個server暫時不參與負載
注:如果使用ip_hash負載時,後面的狀态不能是weight和backup。
1)輪詢(預設)
每個請求按時間順序注意配置設定到不同的機器,相當于LVS中rr算法,如果後端伺服器當機(預設情況下隻檢測80端口,如果後端報502,404,403,503,還是會直接傳回給使用者),則會跳過該伺服器,将請求配置設定給下一個伺服器。
預設算法
2)weight(權重)
在指定的輪詢的基礎上加上權重(預設是rr+weight),權重輪詢和通路成正比,權重越大,轉發的請求也就越多。可以根據伺服器的配置和性能指定權重值大小,可以有效解決新舊伺服器配置設定問題。
示例:
upstream bakend {
server 192.168.0.14weight=10;
server 192.168.0.15 weight=10;
3)ip_hash
每個請求按通路的Ip的hash結果配置設定,當新的請求到達時,先将其用戶端ip通過雜湊演算法哈希出一個值,在随後請求用戶端Ip的哈希值隻要相同,就會被配置設定至同一個伺服器,該排程算法可以解決session問題,但有時會導緻配置設定不均即,無法保證負載均衡。提示:必須是最前端的伺服器,後端也必須直接接應用伺服器
upstream engine {
server 192.168.18.211:80;
server 192.168.18.212:80;
server 192.168.18.213:80 down;
ip_hash;
4)fair(第三方)
按照後端伺服器的響應時間來配置設定請求,響應時間短的優先配置設定。
upstream backend {
server server1;
server server2;
fair;
5)url_hash(第三方)
按通路url的hash結果來配置設定請求,使每個url定向到同一個後端伺服器,後端伺服器為緩存時比較有效。在upstream中加入hash語句,server語句中不能寫入weight等其他的參數,hash_method是使用的hash算法。
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
url_hash在緩存伺服器組中将非常有用
本文轉自楊雲1028 51CTO部落格,原文連結:http://blog.51cto.com/yangrong/1297507,如需轉載請自行聯系原作者