Linux實戰教學筆記30:Nginx反向代理與負載均衡應用實踐

1.1 集羣簡介

  • 簡單地說,集羣就是指一組(若干個)相互獨立的計算機,利用高速通訊網絡組成的一個較大的計算機服務系統,每一個集羣節點(即集羣中的每臺計算機)都是運行各自服務的獨立服務器。這些服務器之間能夠彼此通訊,協同向用戶提供應用程序,系統資源和數據,並以單一系統的模式加以管理。當用戶客戶機請求集羣系統時,集羣給用戶的感受就是一個單一獨立的服務器,而實際上用戶請求的是一組集羣服務器。
  • 打開谷歌,百度的頁面,看起來好簡單,也許你以爲用幾分鐘就能夠製做出類似的網頁,而實際上,這個頁面的背後是由成千上萬臺服務器集羣協同工做的結果。而這麼多的服務器維護和管理,以及相互協調工做也許就是同窗們將來的工做職責了。
  • 若要用一句話描述集羣,即一堆服務器合做作同一件事,這些機器可能須要整個技術團隊架構,設計和統一協調管理,這些機器能夠分佈在一個機房,也能夠分佈在全國全球各個地區的多個機房。

1.2 爲何要使用集羣

(1)高性能php

一些國家重要的計算密集型應用(如天氣預報,核試驗模擬等),須要計算機有很強的運算處理能力。以全世界現有的技術,即便是大型機,其計算能力也是有限的,很難單獨完成此任務。由於計算時間可能會至關長,也許幾天,甚至幾年或更久。所以,對於這類複雜的計算業務,便使用了計算機集羣技術,集中幾十上百臺,甚至成千上萬臺計算機進行計算。css

QQ截圖20170726094121.png-298.5kB

假如你配一個LNMP環境,每次只須要服務10個併發請求,那麼單臺服務器必定會比多個服務器集羣要快。只有當併發或總請求數量超過單臺服務器的承受能力時,服務器集羣纔會體現出優點。html

(2)價格有效性前端

  • 一般一套系統集羣架構,只須要幾臺或數十臺服務器主機便可。與動輒價值上百萬元的專用超級計算機相比便宜了不少。在達到一樣性能需求的條件下,採用計算機集羣架構比採用同等運算能力的大型計算機具備更高的性價比。
  • 早期的淘寶,支付寶的數據庫等核心系統就是使用上百萬元的小型機服務器。後因使用維護成本過高以及擴展設備費用成幾何級數翻倍,甚至成爲擴展瓶頸,人員維護也十分困難,最終使用PC服務器集羣替換之,好比,把數據庫系統從小機結合Oracle數據庫遷移到MySQL開源數據庫結合PC服務器上來。不但成本降低了,擴展和維護也更容易了。

(3)可伸縮性java

當服務負載,壓力增加時,針對集羣系統進行較簡單的擴展便可知足需求,且不會下降服務質量。linux

一般狀況下,硬件設備若想擴展性能,不得不增長新的CPU和存儲器設備,若是加不上去了,就不得不夠買更高性能的服務器,就拿咱們如今的服務器來說,能夠增長的設備老是有限的。若是採用集羣技術,則只須要將新的單個服務器加入現有集羣架構中便可,從訪問的客戶角度來看,系統服務不管是連續性仍是性能上都幾乎沒有變化,系統在不知不覺中完成了升級,加大了訪問能力,輕鬆地實現了擴展。集羣系統中的節點數目能夠增加到幾千乃至上萬個,其伸縮性遠超過單臺超級計算機。android

(4)高可用性nginx

  • 單一的計算機系統總會面臨設備損毀的問題,如CPU,內存,主板,電源,硬盤等,只要一個部件壞掉,這個計算機系統就可能會宕機,沒法正常提供服務。在集羣系統中,儘管部分硬件和軟件也仍是會發生故障,但整個系統的服務能夠是7*24小時可用的。
  • 集羣架構技術可使得系統在若干硬件設備故障發生時仍能夠繼續工做,這樣就將系統的停機時間減小到了最小。集羣系統在提升系統可靠性的同時,也大大減少了系統故障帶來的業務損失,目前幾乎100%的互聯網網站都要求7*24小時提供服務。

(5)透明性git

多個獨立計算機組成的鬆耦合集羣系統構成一個虛擬服務器。用戶或客戶端程序訪問集羣系統時,就像訪問一臺高性能,高可用的服務器同樣,集羣中一部分服務器的上線,下線不會中斷整個系統服務,這對用戶也是透明的。github

(6)可管理性

整個系統可能在物理上很大,但其實容易管理,就像管理一個單一映像系統同樣。在理想情況下,軟硬件模塊的插入能作到即插即用。

(7)可編程性

在集羣系統上,容易開發及修改各種應用程序。

1.3 集羣的常見分類

1.3.1 集羣的常見分類

計算機集羣架構按功能和結構能夠分紅如下幾類:

  • 負載均衡集羣,簡稱LBC或者LB
  • 高可用性集羣,簡稱HAC
  • 高性能計算集羣,簡稱HPC
  • 網格計算集羣

提示:
負載均衡集羣和高可用性集羣是互聯網行業經常使用的集羣架構模式,也是咱們要學習的重點。

1.3.2 不一樣種類的集羣介紹

(1)負載均衡集羣

-負載均衡集羣爲企業提供了更爲實用,性價比更高的系統架構解決方案。負載均衡集羣能夠把不少客戶集中的訪問請求負載壓力盡量平均地分攤在計算機集羣中處理。客戶訪問請求負載一般包括應用程序處理負載和網絡流量負載。這樣的系統很是適合使用同一組應用程序爲大量用戶提供服務的模式,每一個節點均可以承擔必定的訪問請求負載壓力,而且能夠實現訪問請求在各節點之間動態分配,以實現負載均衡。
-負載均衡集羣運行時,通常是經過一個或多個前端負載均衡器將客戶訪問請求分發到後端的一組服務器上,從而達到整個系統的高性能和高可用性。通常高可用性集羣和負載均衡集羣會使用相似的技術,或同時具備高可用性與負載均衡的特色。

負載均衡集羣的做用爲:

  • 分攤用戶訪問請求及數據流量(負載均衡)
  • 保持業務連續性,即7*24小時服務(高可用性)。
  • 應用於Web業務及數據庫從庫等服務器的業務

負載均衡集羣典型的開源軟件包括LVS,Nginx,Haproxy等。以下圖所示:

QQ截圖20170726181402.png-193.2kB

提示:
不一樣的業務會有若干秒的切換時間,DB業務明顯長於Web業務切換時間。

(2)高可用性集羣

通常是指在集羣中任意一個節點失效的狀況下,該節點上的全部任務會自動轉移到其餘正常的節點上。此過程並不影響整個集羣的運行。

  • 當集羣中的一個節點系統發生故障時,運行着的集羣服務會迅速做出反應,將該系統的服務分配到集羣中其餘正在工做的系統上運行。考慮到計算機硬件和軟件的容錯性,高可用性集羣的主要目的是使集羣的總體服務儘量可用。若是高可用性集羣中的主節點發生了故障,那麼這段時間內將由備節點代替它。備節點一般是主節點的鏡像。當它代替主節點時,它能夠徹底接管主節點(包括IP地址及其餘資源)提供服務,所以,使集羣系統環境對於用戶來講是一致的,既不會影響用戶的訪問。
  • 高可用性集羣使服務器系統的運行速度和響應速度會盡量的快。他們常常利用在多臺機器上運行的冗餘節點和服務來相互跟蹤。若是某個節點失敗,它的替補者將在幾秒鐘或更短期內接管它的職責。所以,對於用戶而言,集羣裏的任意一臺機器宕機,業務都不會受影響(理論狀況下)。

高可用性集羣的做用爲:

  • 當一臺機器宕機時,另一臺機器接管宕機的機器的IP資源和服務資源,提供服務。
  • 經常使用於不易實現負載均衡的應用,好比負載均衡器,主數據庫,主存儲對之間。

高可用性集羣經常使用的開源軟件包括Keepalived,Heartbeat等,其架構圖以下圖所示:

QQ截圖20170726203115.png-193.3kB

(3)高性能計算集羣

高性能計算集羣也稱並行計算。一般,高性能計算集羣涉及爲集羣開發的並行應用程序,以解決複雜的科學問題(天氣預報,石油勘探,核反應模擬等)。高性能計算集羣對外就好像一個超級計算機,這種超級計算機內部由數十至上萬個獨立服務器組成,而且在公共消息傳遞層上進行通訊以運行並行應用程序。在生產環境中實際就是把任務切成蛋糕,而後下發到集羣節點計算,計算後返回結果,而後繼續領新任務計算,如此往復。

(4)網格計算集羣

因爲不多用到,在此略

特別提示:
在互聯網網站運維中,比較經常使用的就是負載均衡集羣和高可用性集羣

1.4 經常使用的集羣軟硬件介紹及選型

1.4.1 企業運維中常見的集羣軟硬件產品

互聯網企業經常使用的開源集羣軟件有:Nginx,LVS,Haproxy,Keepalived,heartbeat。

互聯網企業經常使用的商業集羣硬件有:F5,Netscaler,Radware,A10等,工做模式至關於Haproxy的工做模式。

淘寶,趕集網,新浪等公司曾使用過Netscaler負載均衡產品。集羣硬件Netscaler的產品圖以下圖所示:

QQ截圖20170726204518.png-45kB

集羣硬件F5產品以下圖所示:

QQ截圖20170726204604.png-32.5kB

1.4.2 對於集羣軟硬件產品如何選型

下面是我對同窗們的基本選擇建議,更多的建議等你們學完負載均衡內容後再細分講解。

  • 當企業業務重要,技術力量又薄弱,而且但願出錢購買產品及獲取更好的服務時,能夠選擇硬件負載均衡產品,如F5,Netscaler,Radware等,此類公司多爲傳統的大型非互聯網企業,如銀行,證券,金融業及寶馬,奔馳公司等
  • 對於門戶網站來講,大多會並用軟件及硬件產品來分擔單一產品的風險,如淘寶,騰訊,新浪等。融資了的企業會購買硬件產品,如趕集等網站。
  • 中小型互聯網企業,因爲起步階段無利潤可賺或者利潤很低,會但願經過使用開源免費的方案來解決問題,所以會僱傭專門的運維人員進行維護。例如:51CTO等

相比較而言,商業的負載均衡產品成本高,性能好,更穩定,缺點是不能二次開發,開源的負載均衡軟件對運維人員的能力要求較高,若是運維及開發能力強,那麼開源的負載均衡軟件是不錯的選擇,目前的互聯網行業更傾向於使用開源的負載均衡軟件。

1.4.3 如何選擇開源集羣軟件產品

  • 中小企業互聯網公司網站在併發訪問和總訪問量不是很大的狀況下,建議首選Nginx負載均衡,理由是Nginx負載均衡配置簡單,使用方便,安全穩定,社區活躍,使用的人逐漸增多,成爲流行趨勢,另一個實現負載均衡的相似產品爲Haproxy(支持L4和L7負載,一樣優秀,但社區不如Nginx活躍)。
  • 若是要考慮Nginx負載均衡的高可用功能,建議首選Keepalived軟件,理由是安裝和配置簡單,使用方便,安全穩定,與Keepalived服務相似的高可用軟件還有Heartbeat(使用比較複雜,並不建議初學者使用)
  • 若是是大型企業互聯網公司,負載均衡產品可使用LVS+Keepalived在前端作四層轉發(通常是主備或主主,若是須要擴展可使用DNS或前端使用OSPF),後端使用Nginx或者Haproxy作7層轉發(能夠擴展到百臺),再後面是應用服務器,若是是數據庫與存儲的負載均衡和高可用,建議選擇LVS+Heartbeat,LVS支持TCP轉發且DR模式效率很高,Heartbeat能夠配合drbd,不但能夠進行VIP的切換,還能夠支持塊設備級別的數據同步(drbd),以及資源服務的管理。

1.5 Nginx負載均衡集羣介紹

1.5.1 搭建負載均衡服務的需求

負載均衡集羣提供了一種廉價,有效,透明的方法,來擴展網絡設備和服務器的負載,帶寬和吞吐量,同時增強了網絡數據處理能力,提升了網絡的靈活性和可用性。

搭建負載均衡服務的需求以下:

(1)把單臺計算機沒法承受的大規模併發訪問或數據流量分擔到多臺節點設備上,分別進行處理,減小用戶等待響應的時間,提高用戶體驗。
(2)單個重負載的運算分擔到多臺節點設備上作並行處理,每一個節點設備處理結束後,將結果彙總,返回給用戶,系統處理能力獲得大幅度提升。
(3)7*24小時的服務保證,任意一個或多個有限後面節點設備宕機,不能影響業務。

在負載均衡集羣中,同組集羣的全部計算機節點都應該提供相同的服務。集羣負載均衡器會截獲全部對該服務的入站請求。而後將這些請求儘量地平均地分配在全部集羣節點上。

1.5.2 Nginx負載均衡集羣介紹

(1)反向代理與負載均衡概念簡介

  • 嚴格地說,Nginx僅僅是做爲Nginx Proxy反向代理使用的,由於這個反向代理功能表現的效果是負載均衡集羣的效果,因此本文稱之爲Nginx負載均衡。那麼,反向代理和負載均衡有什麼區別呢?
  • 普通負載均衡軟件,例如大名鼎鼎的LVS,其實功能只是對請求數據包的轉發(也可能會改寫數據包),傳遞,其中DR模式明顯的特徵是從負載均衡下面的節點服務器來看,接收到的請求仍是來自訪問負載均衡器的客戶端的真實用戶,而反向代理就不同了,反向代理接收訪問用戶的請求後,會代理用戶從新發起請求代理下的節點服務器,最後把數據返回給客戶端用戶,在節點服務器看來,訪問的節點服務器的客戶端用戶就是反向代理服務器了,而非真實的網站訪問用戶。
  • 一句話,LVS等的負載均衡是轉發用戶請求的數據包,而Nginx反向代理是接收用戶的請求而後從新發起請求去請求其後面的節點。

(2)實現Nginx負載均衡的組件說明

實現Nginx負載均衡的組件主要有兩個,以下表:

QQ截圖20170726213351.png-51.8kB

1.6 快速實踐Nginx負載均衡環境準備

本節先帶同窗們一塊兒操做實戰,讓同窗們對Nginx負載均衡有一個初步的概念,而後再繼續深刻講解Nginx負載均衡的核心知識應用。

QQ截圖20170726214327.png-38.8kB

上圖是快速實踐Nginx負載均衡的邏輯架構圖

在上圖中,全部用戶的請求統一發送到Nginx負載均衡器,而後由負載均衡器根據調度算法來請求Web01和Web02

1.6.1 軟硬件準備

(1)硬件準備

準備4臺VM虛擬機(有物理服務器更佳),兩臺作負載均衡,兩臺作RS,以下表:

HOSTNAME IP 說明
lb01 192.168.0.221 Nginx主負載均衡器
lb02 192.168.0.222 Nginx副負載均衡器
web01 192.168.0.223 Web01服務器
web02 192.168.0.224 Web02服務器

(2)軟件準備

系統:CentOS6.5 x86_64
軟件:nginx-1.10.2.tar.gz

1.6.2 安裝Nginx軟件

下面將在以上4臺服務器上安裝Nginx,這裏只給出安裝的命令部分。

(1)安裝依賴軟件包命令集合。

[root@localhost ~]# yum -y install openssl openssl-devel pcre pcre-devel
[root@localhost ~]# rpm -qa openssl openssl-devel pcre pcre-devel

(2)安裝Nginx軟件包命令集合

[root@localhost ~]# tar xf nginx-1.10.2.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/nginx-1.10.2/
[root@localhost nginx-1.10.2]# useradd -M -s /sbin/nologin nginx
[root@localhost nginx-1.10.2]# ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module && make && make install
[root@localhost nginx]# ln -s /usr/local/nginx/sbin/* /usr/local/sbin/

1.6.3 配置用於測試的Web服務

本小節將在兩臺NginxWeb服務器的節點上操做:配置並查看Web服務器的配置結果。

[root@localhost nginx]# cat conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    log_format main '$remote_addr-$remote_user[$time_local]"$request"'
    '$status $body_bytes_sent "$http_referer"'
    '"$http_user_agent""$http_x_forwarded_for"';
    server {
        listen       80;
        server_name  bbs.yunjisuan.com;
        location / {
            root   html/bbs;
            index  index.html index.htm;
        }
    access_log logs/access_bbs.log main;
    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
            root   html/www;
            index  index.html index.htm;
        }
    access_log logs/access_www.log main;
    }
}


#提示:
這裏故意將www虛擬主機放在下面,便於用後面的參數配置測試效果

配置完成後檢查語法,並啓動Nginx服務

[root@localhost nginx]# /usr/local/nginx/sbin/nginx 
[root@localhost nginx]# netstat -antup | grep nginx
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      4100/nginx

而後填充測試文件數據,以下:

[root@localhost nginx]# mkdir /usr/local/nginx/html/{www,bbs}
[root@localhost nginx]# echo "`hostname -I `www" >> /usr/local/nginx/html/www/index.html
[root@localhost nginx]# cat /usr/local/nginx/html/www/index.html
192.168.0.223 www
[root@localhost nginx]# echo "`hostname -I `bbs" >> /usr/local/nginx/html/bbs/index.html
[root@localhost nginx]# cat /usr/local/nginx/html/bbs/index.html
192.168.0.223 bbs

#提示:
以上操做命令,在Web01上和Web02上是同樣的

配置解析Web01的IP和主機名後,用curl測試一下

[root@localhost nginx]# tail -2 /etc/hosts
192.168.0.223 www.yunjisuan.com
192.168.0.223 bbs.yunjisuan.com
[root@localhost nginx]# curl www.yunjisuan.com
192.168.0.223 www
[root@localhost nginx]# curl bbs.yunjisuan.com
192.168.0.223 bbs

配置解析Web02的IP和主機名後,用curl測試一下

[root@localhost nginx]# vim /etc/hosts
[root@localhost nginx]# tail -2 /etc/hosts
192.168.0.224 www.yunjisuan.com
192.168.0.224 bbs.yunjisuan.com
[root@localhost nginx]# curl www.yunjisuan.com
192.168.0.224 www
[root@localhost nginx]# curl bbs.yunjisuan.com
192.168.0.224 bbs

提示:
(1)不一樣Web測試節點,返回的結果是不一樣的,這是爲了方便測試演示!
(2)經過上面配置就實現了兩臺Web服務器基於域名的虛擬主機配置。

1.6.4 實現一個簡單的負載均衡

本小節將在nginx lb01服務器節點操做(lb02和lb01相同,後文配置負載均衡器高可用時會用到lb02),其準備信息下表。

HOSTNAME IP 說明
lb01 192.168.0.221 Nginx主負載均衡器

下面進行一個簡單的Nginx負載均衡配置,代理www.yunjisuan.com服務,節點爲Web01和Web02.nginx.conf配置文件內容以下:

[root@lb01 nginx]# cat conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream www_server_pools {         #這裏定義Web服務器池,包含了223,224兩個Web節點

    server 192.168.0.223:80 weight=1;

    server 192.168.0.224:80 weight=1;

    }
    server {            #這裏定義代理的負載均衡域名虛擬主機
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;     #訪問www.yunjisuan.com,請求發送給www_server_pools裏面的節點
        }
    }
}

如今檢查語法並啓動。命令以下:

[root@lb01 nginx]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@lb01 nginx]# /usr/local/nginx/sbin/nginx
[root@lb01 nginx]# netstat -antup | grep nginx
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      4105/nginx

而後,檢查負載均衡測試結果。Linux做爲客戶端的測試結果以下:

[root@lb01 nginx]# hostname -I
192.168.0.221 
[root@lb01 nginx]# tail -1 /etc/hosts
192.168.0.221 www.yunjisuan.com         #這裏是lb1負載均衡器IP
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.224 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.224 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.224 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.224 bbs

從上面的測試結果能夠看出來。兩個Web節點按照1:1的比例被訪問。
下面宕掉任意一個Web節點,看看測試結果如何,測試以下:

[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs

能夠看到,網站業務不受影響,訪問請求都定位到了正常的節點上。
如今,宕掉全部Web節點,此時,訪問測試結果以下:

root@lb01 nginx]# curl www.yunjisuan.com
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.10.2</center>
</body>
</html>
[root@lb01 nginx]# curl www.yunjisuan.com
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.10.2</center>
</body>
</html>
[root@lb01 nginx]# curl www.yunjisuan.com
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.10.2</center>
</body>
</html>

能夠看到,Nginx代理下面沒有節點了,所以,Nginx向用戶報告了502錯誤。若是同時開啓全部的Web服務又會怎樣?測試結果以下:

[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.224 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.224 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.224 bbs

結果是Nginx又把請求一比一分配到了Nginx後面的節點上。
同窗們感受如何?Nginx的負載均衡很簡單吧?嗯,就是這麼容易。

1.7 Nginx負載均衡核心組件介紹

1.7.1 Nginx upstream模塊

1.7.1.1 upstream模塊介紹

  • Nginx的負載均衡功能依賴於ngx_http_upsteam_module模塊,所支持的代理方式包括proxy_pass,fastcgi_pass,memcached_pass等,新版Nginx軟件支持的方式有所增長。本文主要講解proxy_pass代理方式。
  • ngx_http_upstream_module模塊容許Nginx定義一組或多組節點服務器組,使用時能夠經過proxy_pass代理方式把網站的請求發送到事先定義好的對應Upstream組的名字上,具體寫法爲「proxy_pass http:// www_server_pools」,其中www_server_pools就是一個Upstream節點服務器組名字。ngx_http_upstream_module模塊官方地址爲:http://nginx.org/en/docs/http/ngx_http_upstream_module.html

1.7.1.2 upstream模塊語法

upstream模塊的語法至關簡單,這裏直接上範例給同窗們講。

範例1:基本的upstream配置案例

upstream www_server_pools {

#       upstream是關鍵字必須有,後面的www_server_pools爲一個Upstream集羣組的名字,能夠本身起名,調用時就用這個名字

server 192.168.0.223:80 weight=5;
server 192.168.0.224:80 weight=10;
server 192.168.0.225:80 weight=15;


#       server關鍵字是固定的,後面能夠接域名(門戶會用)或IP。若是不指定端口,默認是80端口。weight表明權重,數值越大被分配的請求越多,結尾有分號,別忘了。

}

範例2:較完整的upstream配置案例

upstream blog_server_pool {

server 192.168.0.223;   #這行標籤和下行是等價的
server 192.168.0.224:80 weight=1 max_fails=1 fail_timeout=10s;       #這行標籤和上一行是等價的,此行多餘的部分就是默認配置,不寫也能夠。

server 192.168.0.225:80 weight=1 max_fails=2 fail_timeout=20s backup;

#   server最後面能夠加不少參數,具體參數做用看下文的表格

}

範例3:使用域名及socket的upstream配置案例

upstream backend {

server backend1.example.com weight=5;
server backend2.example.com:8080;   #域名加端口。轉發到後端的指定端口上
server unix:/tmp/backend3;  #指定socket文件

#提示:server後面若是接域名,須要內網有DNS服務器或者在負載均衡器的hosts文件作域名解析。

server 192.168.0.223;
server 192.168.0.224:8080;
server backup1.example.com:8080 backup;

#備份服務器,等上面指定的服務器都不可訪問的時候會啓動,backup的用法和Haproxy中用法同樣

server backup2.example.com:8080 backup;

}

若是是兩臺Web服務器作高可用,常規方案就須要keepalived配合,那麼這裏使用Nginx的backup參數經過負載均衡功能就能夠實現Web服務器集羣了,對於企業應用來講,能作集羣就不作高可用。

1.7.1.3 upstream模塊相關說明

upstream模塊的內容應放於nginx.conf配置的http{}標籤內,其默認調度節點算法是wrr(weighted round-robin,即權重輪詢)。下圖爲upstream模塊內部server標籤部分參數說明

QQ截圖20170727194120.png-320.6kB

提示:
以上參數與專業的Haproxy參數很相似,但不如Haproxy的參數易懂。

來看個示例,以下:

upstream backend {

server backend1.example.com weight=5; #若是就是單個Server,不必設置權重
server 127.0.0.1:8080 max_fail=5 fail_timeout=10s;
#當檢測次數等於5的時候,5次連續檢測失敗後,間隔10s再從新檢測。
server unix:/tmp/backend3;
server backup1.example.com:8080 backup; #熱備機器設置

}

須要特別說明的是,若是是Nginx代理Cache服務,可能須要使用hash算法,此時若宕機,可經過設置down參數確保客戶端用戶按照當前的hash算法訪問,這一點很重要。示例配置以下:

upstream backend {

ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;
server backend4.example.com;

}

下面是Haproxy負載均衡器server標籤的配置示例。

#開啓對後端服務器的健康檢測,經過GET /test/index.php來判斷後端服務器的健康狀況
server php_server_1 192.168.0.223:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2
server php_server_2 192.168.0.224:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1
server php_server_bak 192.168.0.225:80 cookie 3 check inter 1500 rise 3 fall 3 backup

上述命令的說明以下:

  • weight:調節服務器的請求分配權重。
  • check:開啓對該服務器健康檢查。
  • inter:設置連續兩次的健康檢查間隔時間,單位毫秒,默認值2000
  • rise:指定多少次連續成功的健康檢查後,便可認定該服務器處於可用狀態。
  • fall:指定多少次不成功的健康檢查後,即認爲服務器爲宕機狀態,默認值3.
  • maxconn:指定可被髮送到該服務器的最大併發鏈接數。

1.7.1.4 upstream模塊調度算法

調度算法通常分爲兩類:
第一類爲靜態調度算法,即負載均衡器根據自身設定的規則進行分配,不須要考慮後端節點服務器的狀況,例如:rr,wrr,ip_hash等都屬於靜態調度算法。
第二類爲動態調度算法,即負載均衡器會根據後端節點的當前狀態來決定是否分發請求,例如:鏈接數少的優先得到請求,響應時間短的優先得到請求。例如:least_conn,fair等都屬於動態調度算法。

下面介紹一下常見的調度算法。

(1) rr輪詢(默認調度算法,靜態調度算法)

按客戶端請求順序把客戶端的請求逐一分配到不一樣的後端節點服務器,這至關於LVS中的rr算法,若是後端節點服務器宕機(默認狀況下Nginx只檢測80端口),宕機的服務器會被自動從節點服務器池中剔除,以使客戶端的用戶訪問不受影響。新的請求會分配給正常的服務器。

(2)wrr(權重輪詢,靜態調度算法)

在rr輪詢算法的基礎上加上權重,即爲權重輪詢算法,當使用該算法時,權重和用戶訪問成正比,權重值越大,被轉發的請求也就越多。能夠根據服務器的配置和性能指定權重值大小,有效解決新舊服務器性能不均帶來的請求分配問題。

(3)ip_hash(靜態調度算法)(會話保持)

每一個請求按客戶端IP的hash結果分配,當新的請求到達時,先將其客戶端IP經過哈希算法哈希出一個值,在隨後的客戶端請求中,客戶IP的哈希值只要相同,就會被分配至同一臺服務器,該調度算法能夠解決動態網頁的session共享問題,但有時會致使請求分配不均,即沒法保證1:1的負載均衡,由於在國內大多數公司都是NAT上網模式,多個客戶端會對應一個外部IP,因此,這些客戶端都會被分配到同一節點服務器,從而致使請求分配不均。LVS負載均衡的-p參數,Keepalived配置裏的persistence_timeout 50參數都相似這個Nginx裏的ip_hash參數,其功能均可以解決動態網頁的session共享問題。

咱們來看一個示例,以下:

upstream yunjisuan_lb{

ip_hash;
server 192.168.0.223:80;
server 192.168.0.224:8080;

}

upstream backend{

ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com down;
server backend4.example.com;

}

注意:
當負載調度算法爲ip_hash時,後端服務器在負載均衡調度中的狀態不能有weight和backup,即便有也不會生效。

(4)fair(動態調度算法)

此算法會根據後端節點服務器的響應時間來分配請求,響應時間短的優先分配。這是更加智能的調度算法。此種算法能夠根據頁面大小和加載時間長短智能地進行負載均衡,也就是根據後端服務器的響應時間來分配請求,響應時間短的優先分配。Nginx自己不支持fair調度算法,若是須要使用這種調度算法,必須下載Nginx相關模塊upstream_fair。

示例以下:

upstream yunjisuan_lb{

server 192.168.0.223;
server 192.168.0.224;
fair;

}

(5)least_conn

least_conn算法會根據後端節點的鏈接數來決定分配狀況,哪一個機器鏈接數少就分發。
除了上面介紹的這些算法外,還有一些第三方調度算法,例如:url_hash,一致性hash算法等,介紹以下。

(6)url_hash算法(web緩存節點)

  • 與ip_hash相似,這裏是根據訪問URL的hash結果來分配請求的,讓每一個URL定向到同一個後端服務器,後端服務器爲緩存服務器時效果顯著。在upstream中加入hash語句,server語句中不能寫入weight等其餘的參數,hash_method使用的是hash算法。
    url_hash按訪問URL的hash結果來分配請求,使每一個URL定向到同一個後端服務器,能夠進一步提升後端緩存服務器的效率命令率。Nginx自己是不支持url_hash的,若是須要使用這種調度算法,必須安裝Nginx的hash模塊軟件包。

url_hash(web緩存節點)和ip_hash(會話保持)相似。示例配置以下:

upstream yunjisuan_lb {

server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;

}

(7)一致性hash算法

一致性hash算法通常用於代理後端業務爲緩存服務(如Squid,Memcached)的場景,經過將用戶請求的URI或者指定字符串進行計算,而後調度到後端的服務器上,此後任何用戶查找同一個URI或者指定字符串都會被調度到這一臺服務器上,所以後端的每一個節點緩存的內容都是不一樣的,一致性hash算法能夠解決後端某個或幾個節點宕機後,緩存的數據動盪最小,一致性hash算法知識比較複雜,詳細內容能夠參考百度上的相關資料,這裏僅僅給出配置示例:

http {
upstream test {

consistent_hash $request_uri;
server 127.0.0.1:9001 id=1001 weight=3;
server 127.0.0.1:9002 id=1002 weight=10;
server 127.0.0.1:9003 id=1003 weight=20;

}

}

雖然Nginx自己不支持一致性hash算法,但Nginx得分支Tengine支持。詳細可參考http://tengine.taobao.org/document_cn/http_upstream_consistent_hash_cn.html

1.7.2 http_proxy_module模塊

1.7.2.1 proxy_pass指令介紹

proxy_pass指令屬於ngx_http_proxy_module模塊,此模塊能夠將請求轉發到另外一臺服務器,在實際的反向代理工做中,會經過location功能匹配指定的URI,而後把接收到的符合匹配URI的請求經過proxy_pass拋給定義好的upstream節點池。該指令官方地址1見:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

下面proxy_pass的使用案例:

(1)將匹配URI爲name的請求拋給http://127.0.0.1/remote/.

location /name/ {

proxy_pass http://127.0.0.1/remote/;

}

(2)將匹配URI爲some/path的請求拋給http://127.0.0.1

location /some/path/ {

proxy_pass http://127.0.0.1;

}

(3)將匹配URI爲name的請求應用指定的rewrite規則,而後拋給http://127.0.0.1

location /name/ {

rewrite /name/( [^/]+ )  /username=$1 break;
proxy_pass http://127.0.0.1;

}

1.7.2.2 http proxy模塊參數

Nginx的代理功能是經過http proxy模塊來實現的。默認在安裝Nginx時已經安裝了http proxy模塊,所以可直接使用http proxy模塊。下面詳細解釋模塊1中每一個選項表明的含義,見下表:

QQ截圖20170727222042.png-93.5kB

QQ截圖20170727222503.png-172.6kB

1.8 Nginx負載均衡配置實戰(上接1.6節)

主機名 IP地址 角色說明
lb01 192.168.0.221 nginx主負載均衡
lb02 192.168.0.222 nginx從負載均衡
Web01 192.168.0.223 nginx web01服務器
Web02 192.168.0.224 nginx web02服務器

1.8.1 查看lb01的配置文件以下:

[root@lb01 nginx]# cat /usr/local/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream www_server_pools {         #默認調度算法wrr,即權重輪詢算法
                                        #雖然定義的www服務器池可是這個服務器池也能夠做爲BBS等業務的服務器池。由於節點服務器的虛擬主機都是根據訪問的主機頭字段區分的。

    server 192.168.0.223:80 weight=1;

    server 192.168.0.224:80 weight=1;

    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;     #經過proxy_pass功能把用過戶的請求交給上面反向代理upstream定義的www_server_pools服務器池處理。
        }
    }
}

如今配置hosts解析到代理服務器lb01上,從新加載服務,訪問測試:

[root@lb01 nginx]# tail -2 /etc/hosts
192.168.0.221 www.yunjisuan.com
192.168.0.221 bbs.yunjisuan.com
[root@lb01 nginx]# /usr/local/nginx/sbin/nginx -s reload
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 bbs
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.224 bbs

從測試結果能夠看出,已經實現了反向代理,負載均衡功能,可是有一個特殊問題,出來的結果並非帶有www的字符串,而是bbs的字符串,根據訪問結果,咱們推測是訪問了Web節點下bbs的虛擬主機,明明代理的是www虛擬主機,爲何結果是訪問了後端的bbs虛擬主機了呢?問題又該如何解決?請同窗們繼續往下看。

1.8.2 反向代理多虛擬主機節點服務器企業案例

上一節代理的結果不對,究其緣由是當用戶訪問域名時確實是攜帶了www.yunjisuan.com主機頭請求Nginx反向代理服務器,可是反向代理向下面節點從新發起請求時,默認並無在請求頭裏告訴節點服務器要找哪臺虛擬主機,因此,Web節點服務器接收到請求後發現沒有主機頭信息,所以,就把節點服務器的第一個虛擬主機發給了反向代理了(節點上第一個虛擬主機放置的是故意這樣放置的bbs)。解決這個問題的方法,就是當反向代理向後從新發起請求時,要攜帶主機頭信息,以明確告訴節點服務器要找哪一個虛擬主機。具體的配置很簡單,就是在Nginx代理www服務虛擬主機配置裏增長以下一行配置便可:

proxy_set_header host $host;

在代理向後端服務器發送的http請求頭中加入host字段信息後,若後端服務器配置有多個虛擬主機,它就能夠識別代理的是哪一個虛擬主機。這是節點服務器多虛擬主機時的關鍵配置。整個Nginx代理配置爲:

[root@lb01 nginx]# cat /usr/local/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream www_server_pools {

    server 192.168.0.223:80 weight=1;

    server 192.168.0.224:80 weight=1;

    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;
        proxy_set_header host $host;    #在代理向後端服務器發送的http請求頭中加入host字段信息,用於當後端服務器配置有多個虛擬主機時,能夠識別代理的是哪一個虛擬主機。這是節點服務器多虛擬主機時的關鍵配置。
        }
    }
}

此時,再從新加載Nginx服務,並用curl測試檢查,結果以下:

[root@lb01 nginx]# /usr/local/nginx/sbin/nginx -s reload
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.223 www
[root@lb01 nginx]# curl www.yunjisuan.com
192.168.0.224 www

能夠看到此次訪問的結果和訪問的域名就徹底對應上了,這樣代理多虛擬主機的節點服務器就不會出問題了

1.8.3 通過反向代理後的節點服務器記錄用戶IP企業案例

完成了反向代理WWW服務後,天然很開心,可是,不久後你用其餘客戶端做爲客戶端測試時,就會發現一個問題,節點服務器對應的WWW虛擬主機的訪問日誌的第一個字段記錄的並非客戶端的IP,而是反向代理服務器的IP,最後一個字段也是「-」!

例如:使用任意windows客戶端計算機,訪問已經解析好代理IP的www.yunjisuan.com後,去節點服務器www服務日誌查看,就會發現以下日誌:

[root@web01 ~]# tail -2 /usr/local/nginx/logs/access_www.log
192.168.0.221--[27/Jul/2017:04:05:22 -0400]"GET / HTTP/1.0"200 18 "-""curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2""-"
192.168.0.221--[27/Jul/2017:04:33:06 -0400]"GET / HTTP/1.0"200 18 "-""curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2""-"

Web01節點服務器對應的WWW虛擬主機的訪問日誌的第一個字段記錄的並非客戶端的IP而是反向代理服務器自己的IP(192.168.0.221),最後一個字段也是一個「-」,那麼如何解決這個問題?其實很簡單,一樣是增長以下一行參數:

proxy_set_header X-Forwarded-For $remote_addr;
#這是反向代理時,節點服務器獲取用戶真實IP的必要功能配置

在反向代理請求後端節點服務器的請求頭中增長獲取的客戶端IP的字段信息,而後節點後端能夠經過程序或者相關的配置接收X-Forwarded-For傳過來的用戶真實IP的信息。

解決上述問題的整個Nginx代理配置爲:

[root@lb01 nginx]# cat /usr/local/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream www_server_pools {

    server 192.168.0.223:80 weight=1;

    server 192.168.0.224:80 weight=1;

    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;
        proxy_set_header host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        #在代理向後端服務器發送的http請求頭中加入X-Forwarded-For字段信息,用於後端服務器程序,日誌等接收記錄真實用戶的IP,而不是代理服務器的IP
        }
    }
}

從新加載Nginx反向代理服務:

[root@lb01 nginx]# /usr/local/nginx/sbin/nginx -s reload

特別注意,雖然反向代理已經配好了,可是節點服務器須要的訪問日誌若是要記錄用戶的真實IP,還必須進行日誌格式配置,這樣才能把代理傳過來的X-Forwarded-For頭信息記錄下來,具體配置爲:

[root@web01 ~]# cat /usr/local/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    log_format main '$remote_addr-$remote_user[$time_local]"$request"'
    '$status $body_bytes_sent "$http_referer"'
    '"$http_user_agent""$http_x_forwarded_for"';
    #就是這裏的「$http_x_forwarded_for」參數,若是但願在第一行顯示,能夠替換掉第一行的$remote_addr變量。
    server {
        listen       80;
        server_name  bbs.yunjisuan.com;
        location / {
            root   html/bbs;
            index  index.html index.htm;
        }
    access_log logs/access_bbs.log main;
    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
            root   html/www;
            index  index.html index.htm;
        }
    access_log logs/access_www.log main;
    }
}

#注意:這裏是客戶端Web01的配置

完成Web01,Web02節點服務器的日誌配置後,就能夠檢查了,注意,不要用curl從反向代理上檢查,最好換一個客戶端檢查,這樣才能看到效果。這裏使用Windows客戶端計算機(IP爲192.168.0.110)訪問已經解析好代理IP的www.yunjisuan.com,以下圖所示:

QQ截圖20170728011520.png-42.1kB

此時,再去節點服務器WWW服務的訪問日誌裏查看,會發現日誌的結尾已經變化了:

[root@web01 ~]# tail -2 /usr/local/nginx/logs/access_www.log 
192.168.0.221--[27/Jul/2017:05:11:22 -0400]"GET / HTTP/1.0"200 18 "-""Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)""192.168.0.110"
192.168.0.221--[27/Jul/2017:05:11:23 -0400]"GET / HTTP/1.0"200 18 "-""Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)""192.168.0.110"

其中,日誌裏的192.168.0.221爲反向代理的IP,對應Nginx日誌格式裏的$remote_addr變量,而日誌結尾的192.168.0.110對應的時日誌格式裏的「$http_x_forwarded_for」變量,即接收了前面反向代理配置中「proxy_set_header X-Forwarded-For $remote_addr;」參數X-Forwarded-For的IP了。
關於X-Forwarded-For的詳細說明,可見http://en.wikipedia.org/wiki/X-Forwwawrded-For。下圖是反向代理相關重要基礎參數的總結,供同窗們參考。

QQ截圖20170728012312.png-148.3kB

1.8.4 與反向代理配置相關的更多參數說明

除了具備多虛擬主機代理以及節點服務器記錄真實用戶IP的功能外,Nginx軟件還提供了至關多的做爲反向代理和後端節點服務器對話的相關控制參數,具體見前面在講解proxy模塊時提供的圖表。

相信同窗們對這些參數有了必定了解了,因爲參數衆多,最好把這些參數放到一個配置文件裏,而後用include方式包含到虛擬主機配置裏,效果以下:

[root@lb01 conf]# cat /usr/local/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream www_server_pools {

    server 192.168.0.223:80 weight=1;

    server 192.168.0.224:80 weight=1;

    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://www_server_pools;
        include proxy.conf;         #這就是包含的配置,具體配置內容見下文
        }
    }
}

[root@lb01 conf]# cat proxy.conf 
proxy_set_header host $host;
proxy_set_header x-forwarded-for $remote_addr;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

更多Nginx反向代理參數說明
http://nginx.org/en/docs/http/ngx_http_proxy_module.html

1.8.3 根據URL中的目錄地址實現代理轉發

1.8.3.1 根據URL中的目錄地址實現代理轉發的說明

爲了讓同窗們能學以至用。仍是經過真實的企業案例模擬來給你們講解這部分的知識

案例背景:
經過Nginx實現動靜分離,即經過Nginx反向代理配置規則實現讓動態資源和靜態資源及其餘業務分別由不一樣的服務器解析,以解決網站性能,安全,用戶體驗等重要問題。

下圖爲企業常見的動靜分離集羣架構圖,此架構圖適合網站前端只使用同一個域名提供服務的場景,例如,用戶訪問的域名是www.yunjisuan.com,而後,當用戶請求www.yunjisuan.com/upload/xx地址時候,代理會分配請求到上傳服務器池處理數據;當用戶請求www.yunjisuan.com/static/xx地址的時候,代理會分配請求到靜態服務器池請求數據;當用戶請求www.yunjisuan.com/xx地址的時候,即不包含上述指定的目錄地址路徑時,代理會分配請求到默認的動態服務器池請求數據(注意:上面的xx表示任意路徑)。

QQ截圖20170728093705.png-123kB

1.8.3.2 準備:案例配置實戰

先進行企業案例需求梳理:

  • 當用戶請求www.yunjisuan.com/upload/xx地址時,實現由upload上傳服務器池處理請求。
  • 當用戶請求www.yunjisuan.com/static/xx地址時,實現由靜態服務器池處理請求。
  • 除此之外,對於其餘訪問請求,全都由默認的動態服務器池處理請求。

瞭解了需求後,就能夠進行upstream模塊服務器池的配置了。

#static_pools爲靜態服務器池,有一個服務器,地址爲192.168.0.223,端口爲80.

upstream static_pools {

server 192.168.0.223:80 weght=1;

}

#upload_pools爲上傳服務器池,有一個服務器地址爲192.168.0.224,端口爲80.

upstream upload_pools {

server 192.168.0.224:80 weight=1;

}

#default_pools爲默認的服務器池,即動態服務器池,有一個服務器,地址爲192.168.0.225,端口爲80.

upstream default_pools {

server 192.168.0.225:80 weight=1;

}

#提示:須要增長一臺測試Web節點Web03(ip:192.168.0.225),配置與Web01,Web02同樣。

下面利用location或if語句把不一樣的URI(路徑)請求,分給不一樣的服務器池處理,具體配置以下。

方案1:以location方案實現

#將符合static的請求交給靜態服務器池static_pools,配置以下:
location /static/ {

proxy_pass http://static_pools;
include proxy.conf;

}

#將符合upload的請求交給上傳服務器池upload_pools,配置以下:
location /upload/ {

proxy_pass http://upload_pools;
include proxy.conf;

}

#不符合上述規則的請求,默認所有交給動態服務器池default_pools,配置以下:
location / {

proxy_pass http://default_pools;
include proxy.conf;

}

方案2:以if語句實現。

if ($request_uri ~* "^/static/(.*)$")
{
proxy_pass http://static_pools/$1;
}

if ($request_uri ~* "^/upload/(.*)$")
{
proxy_pass http://upload_pools/$1;
}

location / {

proxy_pass http://default_pools;
include proxy.conf;

}

下面以方案1爲例進行講解,Nginx反向代理的實際配置以下:

[root@lb01 ~]# cat /usr/local/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream static_pools {

    server 192.168.0.223:80 weight=1;

    }
    upstream upload_pools {

    server 192.168.0.224:80 weight=1;

    }
    upstream default_pools {

    server 192.168.0.225:80 weight=1;

    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://default_pools;
        include proxy.conf;
        }
    location /static/ {
        proxy_pass http://static_pools;
        include proxy.conf;
    }
    location /upload/ {
        proxy_pass http://upload_pools;
        include proxy.conf;
    }
    
    }
}

從新加載配置生效,以下:

[root@lb01 ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@lb01 ~]# /usr/local/nginx/sbin/nginx -s reload

暫時不要馬上測試成果,爲了實現上述代理的測試,還須要在Web01和Web02上作節點的測試配置,才能更好地展現測試效果。
以Web01做爲static靜態服務,地址端口爲:192.168.0.223:80,須要事先配置一個用於測試靜態的地址頁面,並測試訪問,肯定它會返回正確結果。操做步驟以下:

[root@web01 ~]# cd /usr/local/nginx/html/www/
[root@web01 www]# mkdir static
[root@web01 www]# echo "static_pools" >> static/index.html
[root@web01 www]# curl http://www.yunjisuan.com/static/index.html      #這裏的www.yunjisuan.com是解析過的Web01的本地IP
static_pools

#提示:測試的靜態地址爲http://www.yunjisuan.com/static/index.html,注意,是帶static路徑的地址。

以Web02做爲upload上傳服務,地址端口爲:192.168.0.224:80,須要事先配置一個用於測試上傳服務的地址頁面,並測試訪問,肯定它會返回正確結果。操做步驟以下:

[root@web02 ~]# cd /usr/local/nginx/html/www/
[root@web02 www]# mkdir upload
[root@web02 www]# echo "upload_pools" >> upload/index.html
[root@web02 www]# curl http://www.yunjisuan.com/upload/index.html      #這裏的www.yunjisuan.com是解析過的Web02的本地IP
upload_pools

#提示:測試的上傳地址爲http://www.yunjisuan.com/upload/index.html,注意,是帶upload路徑的地址。

在Web03做爲動態服務節點,地址端口爲192.168.0.225:80,一樣須要事先配置一個默認的地址頁面,並測試訪問,肯定它會返回正確結果。操做步驟以下:

[root@web03 www]# cd /usr/local/nginx/html/www
[root@web03 www]# echo "default_pools" >> index.html
[root@web03 www]# curl http://www.yunjisuan.com
default_pools

以上準備了上臺Web節點服務器,分別加入到了upstream定義的不一樣服務器池,表明三組不一樣的業務集羣組,從本機經過hosts解析各自的域名,而後測試訪問,其地址與實際訪問的內容輸出請對照下表:

節點 IP及端口 測試地址 字符串爲表明業務
web01 192.168.0.223:80 http://www.yunjisuan.com/static/index.html static_pools
web02 192.168.0.224:80 http://www.yunjisuan.com/upload/index.html upload_pools
web03 192.168.0.225:80 http://www.yunjisuan.com default_pools

使用客戶端計算機訪問測試時,最好選用集羣之外的機器,這裏先在瀏覽器客戶端的hosts文件裏把www.yunjisuan.com解析到Nginx反向代理服務器的IP,而後訪問上述URL,看代理是否是把請求正確地轉發到了指定的服務器上。若是能夠獲得與上表對應的內容,表示配置的Nginx代理分發的徹底正確,由於若是分發請求到錯誤的機器上就沒有對應的URL頁面內容,輸出會是404錯誤。

QQ截圖20170728104914.png-65.9kB

1.8.3.3 根據URL目錄地址轉發的應用場景

  • 根據HTTP的URL進行轉發的應用狀況,被稱爲第7層(應用層)的負載均衡,而LVS的負載均衡通常用於TCP等的轉發,所以被稱爲第4層(傳輸層)的負載均衡。
  • 在企業中,有時但願只用一個域名對外提供服務,不但願使用多個域名對應同一個產品業務,此時就須要在代理服務器上經過配置規則,使得匹配不一樣規則的請求會交給不一樣的服務器池處理。這類業務有:
  • 業務的域名沒有拆封或者不但願拆分,但但願實現動靜分離,多業務分離,這在前面已經講解過案例了。
  • 不一樣的客戶端設備(例如:手機和PC端)使用同一個域名訪問同一個業務網站,就須要根據規則將不一樣設備的用戶請求交給後端不一樣的服務器處理,以便獲得最佳用戶體驗。這也是很是重要的,接下來,我就帶同窗們看看這類的相關案例。

1.8.4 根據客戶端的設備(user_agent)轉發實踐需求

1.8.4.1 根據客戶端的設備(user_agent)轉發實踐需求

在企業中,爲了讓不一樣的客戶端設備用戶訪問有更好的體驗,須要在後端架設不一樣服務器來知足不一樣的客戶端訪問,例如:移動客戶端訪問網站,就須要部署單獨的移動服務器及程序,體驗才能更好,並且移動端還分蘋果,安卓,Ipad等,在傳統的狀況下,通常用下面的辦法解決這個問題。

(1)常規4層負載均衡解決方案架構

在常規4層負載均衡架構下,可使用不一樣的域名來實現這個需求,例如,人爲分配好讓移動端用戶訪問wap.yunjisuan.com,PC客戶端用戶訪問www.yunjisuan.com,經過不一樣域名來引導用戶到指定的後端服務器,該解決方案的架構圖以下:

QQ截圖20170728114132.png-137.4kB

此解決方案的最大問題就是不一樣客戶端的用戶要記住對應的域名!而絕大多數用戶只會記住www.yunjisuan.com,不會記住wap.yunjisuan.com,這樣一來就會致使用戶體驗不是很好。有沒有辦法讓全部客戶端用戶只訪問一個統一的www.yunjisuan.com這個地址,還能讓不一樣客戶端設備都能有更好的訪問體驗呢?固然有!那就是下面的第7層負載均衡解決方案。

(2)第7層負載均衡解決方案

在第7層負載均衡架構下,就能夠不須要人爲拆分域名了,對外只須要用一個域名,例如www.yunjisuan.com,經過獲取用戶請求中的設備信息(利用$http_user_agent獲取),根據這些信息轉給後端合適的服務器處理,這個方案最大好處就是不須要讓用戶記憶多個域名了,用戶只須要記住主網站地址www.yunjisuan.com,剩下的由網站服務器處理,這樣的思路大大地提高了用戶訪問體驗,這是當前企業網站很是經常使用的解決方案。

下面咱們就來說解此方案,下圖描述了上述解決方案相應的架構邏輯圖

QQ截圖20170728115018.png-127.2kB

1.8.4.2 根據客戶端設備(user_agent)轉發請求實踐

這裏仍是使用static_pools,upload_pools做爲本次實驗的後端服務器池。下面先根據計算機客戶端瀏覽器的不一樣設置對應的匹配規則。(因爲沒有合適的實驗驗證環境,這裏僅做需求實現的細節講解)

location / {

if ($http_user_agent ~* "MSIE")
#若是請求的瀏覽器爲微軟IE瀏覽器(MSIE),則讓請求由static_pools池處理
{
proxy_pass http://static_pools;
}
if ($http_user_agent ~* "Chrome")
#若是請求的瀏覽器爲谷歌瀏覽器(Chrome),則讓請求由upload_pools池處理
{
proxy_pass http://upload_pools;
}
proxy_pass http://default_pools;
#其餘客戶端,由default_pools處理
include proxy.conf;
}

除了針對瀏覽器外,上述「$http_user_agent」變量也可針對移動端,好比安卓,蘋果,Ipad設備進行匹配,去請求指定的服務器,具體細節配置以下:

location / {
if ($http_user_agent ~* "android")
{
proxy_pass http://android_pools;    #這裏是android服務器池
}
if ($http_user_agent ~* "iphone")
{
proxy_pass http://iphone_pools;    #這裏是iphone服務器池
}
proxy_pass http://pc_pools;     #這裏是默認的pc服務器池
include extra/proxy.conf;
}
  • 這部分的測試同窗們能夠回家經過局域網的Wifi功能來實現,用手機等鏈接到wifi,而後訪問服務器的IP測試就能夠了。測試時,請用節點的第一個虛擬主機請求測試,這樣就不須要本地hosts域名解析了,由於手機端測試作hosts解析也不容易,固然有公網的域名和服務器測試最佳,這部分的配合和測試與瀏覽器設備實踐幾乎同樣,所以,這裏的測試就留給同窗們了,看看能不能達到你想的測試效果?
  • 此外,查找移動設備的user_agent對應的具體名稱時,仍是先用對應的設備經過IP地址訪問節點服務器,而後看訪問日誌,注意IP訪問只找第一個虛擬主機的網站。
192.168.0.110--[28/Jul/2017:02:12:10 -0400]"GET / HTTP/1.1"200 18 "-""Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)""-" 
#PCwindows訪問日誌

192.168.0.106--[28/Jul/2017:02:12:22 -0400]"GET / HTTP/1.1"200 18 "-""Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.0 Mobile/14G60 Safari/602.1""-"

#蘋果iphone6手機設備訪問的日誌。

1.8.5 根據文件擴展名實現代理轉發

除了根據URI路徑及user_agent轉發外,還能夠實現根據文件擴展名進行轉發(這裏僅以細節配置做爲講解內容,如需測試請同窗們自行實驗)

1.8.5.1 相關server配置

#先看看location方法的匹配規則,以下:

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css|js)$ {

proxy_pass http://static_pools;
include proxy.conf;

}

#下面是if語句方法的匹配規則:
if ($request_uri ~* ".*\.(php|php5)$")
{

proxy_pass http://php_server_pools;

}

if ($request_uri ~* ".*\.(jsp|jsp*|do|do*)$")
{

proxy_pass http://java_server_pools;

}

1.8.5.2 根據擴展名轉發的應用場景

可根據擴展名實現資源的動靜分離訪問,如圖片,視頻等請求靜態服務器池,PHP,JSP等請求動態服務器池。

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

}

在開發沒法經過程序實現動靜分離的時候,運維能夠根據資源實體進行動靜分離,而不依賴於開發,具體實現策略是先把後端的服務器分紅不一樣的組。注意,每組服務器的程序都是相同的,由於開發沒有把程序拆開,分組後,在前端代理服務器上經過講解過的路徑,擴展名進行規則匹配,從而實現請求的動靜分離。

1.9 Nginx負載均衡檢測節點狀態

淘寶技術團隊開發了一個Tengine(Nginx的分支)模塊Nginx_upstream_check_module,用於提供主動式後端服務器健康檢查。經過它能夠檢測後端realserver的健康狀態,若是後端realserver不可用,則全部的請求就不會轉發到該節點上。
Tengine原生支持這個模塊,而Nginx則須要經過打補丁的方式將該模塊添加到Nginx中。補丁下載地址:https://github.com/yaoweibin/nginx_upstream_check_module。下面介紹如何使用這個模塊。

(1)安裝nginx_upstream_check_module模塊

#系統已經安裝了nginx-1.10.2軟件
[root@lb01 ~]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.10.2

#下載補丁包
[root@lb01 ~]# wget https://codeload.github.com/yaoweibin/nginx_upstream_check_module/zip/master
[root@lb01 ~]# unzip master
[root@lb01 ~]# ls
anaconda-ks.cfg  install.log  install.log.syslog  master  nginx-1.10.2.tar.gz  nginx_upstream_check_module-master
[root@lb01 nginx-1.10.2]# mv ~/nginx_upstream_check_module-master /usr/src/

#由於是對源程序打補丁,因此還須要Nginx源程序
[root@lb01 ~]# cd /usr/src/nginx-1.10.2/
[root@lb01 nginx-1.10.2]# patch -p0 < /usr/src/nginx_upstream_check_module-master/check_1.9.2+.patch
patching file src/http/modules/ngx_http_upstream_hash_module.c
patching file src/http/modules/ngx_http_upstream_ip_hash_module.c
patching file src/http/modules/ngx_http_upstream_least_conn_module.c
patching file src/http/ngx_http_upstream_round_robin.c
patching file src/http/ngx_http_upstream_round_robin.h

#備份源安裝程序
[root@lb01 nginx-1.10.2]# cd /usr/local/
[root@lb01 local]# ls
bin  etc  games  include  lib  lib64  libexec  nginx  sbin  share  src
[root@lb01 local]# mv nginx{,.ori}
[root@lb01 local]# ls
bin  etc  games  include  lib  lib64  libexec  nginx.ori  sbin  share  src
[root@lb01 local]# cd /usr/src/nginx-1.10.2/

#從新進行編譯,編譯的參數要和之前一致,最後加上 --add-module=/usr/src/nginx_upstream_check_module-master/

[root@lb01 nginx-1.10.2]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --add-module=/usr/src/nginx_upstream_check_module-master/
[root@lb01 local]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.10.2
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) 
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --add-module=/usr/src/nginx_upstream_check_module-master/

#拷貝源配置文件到當前Nginx的安裝目錄下
[root@lb01 local]# pwd
/usr/local
[root@lb01 local]# cp nginx.ori/conf/nginx.conf nginx/conf/
cp: overwrite `nginx/conf/nginx.conf'? y
[root@lb01 local]# cp nginx.ori/conf/proxy.conf nginx/conf/
[root@lb01 local]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

(2)配置Nginx健康檢查,以下:

[root@lb01 local]# cat nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream static_pools {

    server 192.168.0.223:80 weight=1;
    server 192.168.0.224:80 weight=1;
    check interval=3000 rise=2 fall=5 timeout=1000 type=http;   #對static服務器池開啓健康監測

    }
    upstream default_pools {

    server 192.168.0.225:80 weight=1;

    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://default_pools;
        include proxy.conf;
        }
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
        proxy_pass http://static_pools;
        include proxy.conf;
    }
    location /status {
    
    check_status;           #啓動健康檢查模塊
    access_log off;         #關閉此location的訪問日誌記錄

    }
    
    }
}

重啓lb1的nginx服務

[root@lb01 local]# /usr/local/nginx/sbin/nginx 
[root@lb01 local]# netstat -antup | grep nginx
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      7008/nginx 

#注意此處必須重啓Nginx,不能從新加載

check interval=3000 rise=2 fall=5 timeout=1000 type=http;
上面配置的意思時,對static_pools這個負載均衡條目中的全部節點,每隔3秒檢測一次,請求2次正常則標記realserver狀態爲up,若是檢測5次都失敗,則標記realserver的狀態爲down,超時時間爲1秒,檢查的協議是HTTP。
詳細用法見官網:http://tengine.taobao.org/document_cn/http_upstream_check_cn.html

訪問頁面時,顯示以下圖所示:

QQ截圖20170728203028.png-44.9kB

在lb1配置文件的upstream default_pools{}裏也加入健康監測命令,以下:

[root@lb01 local]# cat nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream static_pools {

    server 192.168.0.223:80 weight=1;
    server 192.168.0.224:80 weight=1;
    check interval=3000 rise=2 fall=5 timeout=1000 type=http;          #對static服務器池開啓健康監測

    }
    upstream default_pools {

    server 192.168.0.225:80 weight=1;
    check interval=3000 rise=2 fall=5 timeout=1000 type=http;       #對default服務器池開啓健康監測
    
    }
    server {
        listen       80;
        server_name  www.yunjisuan.com;
        location / {
        proxy_pass http://default_pools;
        include proxy.conf;
        }
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
        proxy_pass http://static_pools;
        include proxy.conf;
    }
    location /status {
    
    check_status;           #啓動健康檢查模塊
    access_log off;         #關閉此location的訪問日誌記錄

    }
    
    }
}

再次訪問健康監測頁面時,顯示以下圖所示:

QQ截圖20170728204324.png-48kB

關閉任意一個RS節點後(3個Web服務器任選一個關閉nginx服務)

#關閉Web02的nginx服務
[root@web02 ~]# /usr/local/nginx/sbin/nginx -s stop

再次訪問健康監測頁面時,顯示以下圖所示:

QQ截圖20170728204638.png-44.7kB

1.10 proxy_next_upstream 參數補充

當Nginx接收後端服務器返回proxy_next_upstream參數定義的狀態碼時,會將這個請求轉發給正常工做的後端服務器,例如500,502,503,504,此參數能夠提高用戶的訪問體驗,具體配置以下:

server {

listen 80;
server_name www.yunjisuan.com;
location / {

proxy_pass http://static_pools;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
include proxy.conf;

}

}

1.11 本章重點回顧

  1. 集羣的概念,分類,軟硬件知識。
  2. upstream負載均衡模塊知識
  3. http_proxy代理模塊知識及相關參數
  4. 基於URI路徑,user_agent,擴展名規則知識及實踐案例。
  5. 監測Nginx代理下面節點的健康狀態。
相關文章
相關標籤/搜索