1. 程式人生 > >Linux系統——Nginx反向代理與負載均衡

Linux系統——Nginx反向代理與負載均衡

叢集
叢集是指一組(若干個)相互獨立的計算機,利用高速通訊網路組成的一個較大的計算機服務系統,每個叢集節點(即叢集中的每臺計算機)都是運用各自服務的獨立伺服器。這些伺服器之間可以彼此通訊,協同向用戶提供應用程式,系統資源和資料,並以單一系統的模式加以管理。當用戶客戶機請求集群系統時,叢集給使用者的感覺就是一個單一獨立的伺服器,而實際上使用者請求的是一組叢集伺服器。

特點:
(1)高效能
使用者通過Internet到公司的閘道器,閘道器通過防火牆,調載到前端的主負載均衡伺服器上(有主有備,預防單點問題),主負載均衡根據演算法傳送給web叢集中的一臺LNMP Web伺服器,動態nginx傳送給php,PHP找到資料庫,資料庫尋找主資料庫(還有備份資料庫),利用主從複製架構(主負責寫,從負責讀),此時分離出三個“從”同為從的資料 庫前端有一組負載均衡(一主一從,負擔讀的壓力),都是負責讀;當用戶讀取資料是,直接到讀的負載均衡器
時間久了,隨著叢集的擴大,MySQL主庫壓力過大,承受不了,進行主從複製,讀寫分離(select讀,insert寫),

(靜態網頁由Nginx處理,動態網頁由PHP找資料庫,其中PHP通過解析開發寫的程式碼然後找MySQL)
(2)價格有效性
(3)可伸縮性
(4)高可用性
(5)透明性
(6)可管理性
(7)可程式設計性

##### 叢集的常見分類
計算機叢集架構按功能和結構可以分成以下幾類:
1. 負載均衡叢集,簡稱LBC或者LB
分攤使用者訪問請求及資料流量(負載均衡)
保持業務連續性,即7*24小時服務(高可用性)。
應用於Web業務及資料庫從庫等伺服器的業務
負載均衡叢集典型的開源軟體包括LVS,Nginx,Haproxy等。
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181129142350834.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
LVS:四層負載均衡裝置,通過修改IP頭部和MAC頭部實現對資料包的完全==轉發==;速度快,效率高,但由於只能到四層,因此實現功能少
Nginx:七層負載均衡裝置,效率低,但是實現的功能多
Nginx==反向代理==接收訪問使用者的請求後,會代理使用者重新發起請求代理下的節點伺服器,最後把資料返回給客戶端使用者,在節點伺服器看來,訪問的節點伺服器的客戶端使用者就是反向代理伺服器了,而非真實的網站訪問使用者。
==LVS等的負載均衡是轉發使用者請求的資料包,而Nginx反向代理是接收使用者的請求然後重新發起請求去請求其後面的節點。==
2. 高可用性叢集,簡稱HAC
指在叢集中任意一個節點失效的情況下,該節點上的所有任務會自動轉移到其他正常的節點上。此過程並不影響整個叢集的執行。
高可用性叢集的作用為:

當一臺機器宕機時,另外一臺機器接管宕機的機器的IP資源和服務資源,提供服務。
常用於不易實現負載均衡的應用,比如負載均衡器,主資料庫,主儲存對之間。
高可用性叢集常用的開源軟體包括Keepalived,Heartbeat等。
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181129144449910.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
3. 高效能運算叢集,簡稱HPC
高效能運算叢集也稱平行計算。通常,高效能運算叢集涉及為叢集開發的並行應用程式,以解決複雜的科學問題(天氣預報,石油勘探,核反應模擬等)。高效能運算叢集對外就好像一個超級計算機,這種超級計算機內部由數十至上萬個獨立伺服器組成,並且在公共訊息傳遞層上進行通訊以執行並行應用程式。在生產環境中實際就是把任務切成蛋糕,然後下發到叢集節點計算,計算後返回結果,然後繼續領新任務計算,如此往復。
4. 網格計算叢集

###### 對於叢集軟硬體產品如何選型
當企業業務重要,技術力量又薄弱,並且希望出錢購買產品及獲取更好的服務時,可以選擇硬體負載均衡產品,如F5,Netscaler,Radware等,此類公司多為傳統的大型非網際網路企業,如銀行,證券,金融業及寶馬,賓士公司等
對於入口網站來說,大多會並用軟體及硬體產品來分擔單一產品的風險,如淘寶,騰訊,新浪等。融資了的企業會購買硬體產品,如趕集等網站。
中小型網際網路企業,由於起步階段無利潤可賺或者利潤很低,會希望通過使用開源免費的方案來解決問題,因此會僱傭專門的運維人員進行維護。例如:51CTO等

### 負載均衡環境搭建
環境部署:一臺nginx伺服器(編譯安裝nginx),兩臺WEB伺服器(web01與web02配置環境完全相同,編譯安裝nginx)
nginx服務端 192.168.239.129
web01伺服器 192.168.239.130
web02伺服器 192.168.239.131

1.nginx安裝
```
[[email protected] ~]# tar xf nginx-1.10.2.tar.gz -C /usr/src/
[[email protected] ~]# cd /usr/src/nginx-1.10.2/
[[email protected] ~]# mount /dev/sr0 /media/cdrom
[[email protected] nginx-1.10.2]# yum -y install pcre-devel openssl-devel
[[email protected] nginx-1.10.2]# useradd -s /sbin/nologin -M www
[[email protected] nginx-1.10.2]# ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
[[email protected] nginx-1.10.2]# make && make install
[[email protected] nginx-1.10.2]# ln -s /usr/local/nginx/sbin/* /usr/local/sbin/
[[email protected] conf]# cd /usr/local/nginx/conf/
[[email protected] conf]# egrep -v "#|^$" nginx.conf.default > nginx.conf
[[email protected] conf]# vim nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream default_server { # upstream伺服器池 default_server市伺服器池的名字
server 192.168.239.130; #server就是一個RS節點,預設權重weight=1(負載均衡是按照權重比分配的)
server 192.168.239.131;
}
server {
listen 80;
server_name www.yunjisuan.com;
location / {
proxy_pass http://default_server;
proxy_set_header host $host; #在代理向後端伺服器傳送的http請求頭中加入host欄位資訊,用於當後端伺服器配置有多個虛擬主機時,可以識別代理的是哪個虛擬主機。這是節點伺服器多虛擬主機時的關鍵配置。
proxy_set_header x-forward-for $remote_addr; #在代理向後端伺服器傳送的http請求頭中加入X-Forwarded-For欄位資訊,用於後端伺服器程式,日誌等接收記錄真實使用者的IP,而不是代理伺服器的IP
}
}
}
[[email protected] conf]# /usr/local/nginx/sbin/nginx
[[email protected] conf]# netstat -antup | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx
# nginx編譯完畢
[[email protected] html]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.239.129 www.yunjisuan.com

```
2.配置 web伺服器的nginx.conf配置檔案
web01與weo02配置檔案相同
```
[[email protected] conf]# vim 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"' #來源IP、來源使用者、時間、請求
'$status $body_bytes_sent "$http_referer"' #狀態碼、主體(顯示傳送的大小)、來源瀏覽器、使用者客戶端、使用者的IP
'"$http_user_agent""$http_x_forwarded_for"'; #日誌格式化,節點伺服器需要的訪問日誌如果要記錄使用者的真實IP,還必須進行日誌格式配置,這樣才能把代理傳過來的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; #啟用日誌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;
}
}
[[email protected] conf]# /usr/local/nginx/sbin/nginx
[[email protected] conf]# netstat -antup | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx
[[email protected] nginx]# mkdir /usr/local/nginx/html/{www,bbs}
[[email protected] nginx]# echo "`hostname -I `www" >> /usr/local/nginx/html/www/index.html
[[email protected] nginx]# cat /usr/local/nginx/html/www/index.html
192.168.239.130 www
[[email protected] nginx]# echo "`hostname -I `bbs" >> /usr/local/nginx/html/bbs/index.html
[[email protected] nginx]# cat /usr/local/nginx/html/bbs/index.html
192.168.239.130 bbs
[[email protected] conf]# vim /etc/hosts
192.168.239.130 www.yunjisuan.com bbs.yunjisuan.com
[[email protected] conf]# curl www.yunjisuan.com
192.168.239.130 www
[[email protected] conf]# curl bbs.yunjisuan.com
192.168.239.130 bbs

# web02同上操作
```
3. 檢查負載均衡測試結果

```
[[email protected] conf]# hostname -I
192.168.239.129
[roo[email protected] conf]# vim /etc/hosts
192.168.239.129 www.yunjisuan.com
[[email protected] conf]# curl www.yunjisuan.com
192.168.239.130 www
[[email protected] conf]# curl www.yunjisuan.com
192.168.239.131 www

```
#### Nginx負載均衡核心元件介紹
##### Nginx upstream模組
ngx_http_upstream_module模組允許Nginx定義一組或多組節點伺服器組,使用時可以通過proxy_pass代理方式把網站的請求傳送到事先定義好的對應Upstream組的名字上,具體寫法為“proxy_pass http:// www_server_pools”,其中www_server_pools就是一個Upstream節點伺服器組名字。
upstream伺服器池自帶健康監測功能
```
upstream default_server { # upstream伺服器池 default_server市伺服器池的名字
server 192.168.239.130; #server就是一個RS節點,預設權重輪詢weight=1(負載均衡是按照權重比分配的)
server 192.168.239.131; #server關鍵字是固定的,後面可以接域名或IP。如果不指定埠,預設是80埠。weight代表權重,數值越大被分配的請求越多
}
```
使用域名及socket
```
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;

}
```
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181129152227282.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)

```
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;

}

#weight:調節伺服器的請求分配權重。
check:開啟對該伺服器健康檢查。
inter:設定連續兩次的健康檢查間隔時間,單位毫秒,預設值2000
rise:指定多少次連續成功的健康檢查後,即可認定該伺服器處於可用狀態。
fall:指定多少次不成功的健康檢查後,即認為伺服器為宕機狀態,預設值3.
maxconn:指定可被髮送到該伺服器的最大併發連線數。
```
##### upstream模組排程演算法
排程演算法一般分為兩類:
第一類為靜態排程演算法,即負載均衡器根據自身設定的規則進行分配,不需要考慮後端節點伺服器的情況,例如:rr,wrr,ip_hash等都屬於靜態排程演算法。
第二類為動態排程演算法,即負載均衡器會根據後端節點的當前狀態來決定是否分發請求,例如:連線數少的優先獲得請求,響應時間短的優先獲得請求。例如:least_conn,fair等都屬於動態排程演算法。
(1) rr輪詢(預設排程演算法,靜態排程演算法 1:1)

按客戶端請求順序把客戶端的請求逐一分配到不同的後端節點伺服器,這相當於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共享問題。(同一個ip來源地址永遠返回給同一節點伺服器,達到會話保持的效果,失去負載均衡作用,導致後方請求數不均衡)
==將session儲存在資料庫快取中,達到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。
(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模組軟體包。

(7)一致性hash演算法

一致性hash演算法一般用於代理後端業務為快取服務(如Squid,Memcached)的場景,通過將使用者請求的URI或者指定字串進行計算,然後排程到後端的伺服器上,此後任何使用者查詢同一個URI或者指定字串都會被排程到這一臺伺服器上,因此後端的每個節點快取的內容都是不同的,一致性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;

}

}
```
##### http_proxy_module模組
proxy_pass指令屬於ngx_http_proxy_module模組,此模組可以將請求轉發到另一臺伺服器,在實際的反向代理工作中,會通過location功能匹配指定的URI,然後把接收到的符合匹配URI的請求通過proxy_pass拋給定義好的upstream節點池。
(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;

}
```
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181129161029444.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181129161042288.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181130114232498.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
##### nginx反向代理的優化

```
[[email protected] conf]# vim nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream default_server { # upstream伺服器池 default_server市伺服器池的名字
server 192.168.239.130; #server就是一個RS節點,預設權重weight=1(負載均衡是按照權重比分配的)
server 192.168.239.131;
}
server {
listen 80;
server_name www.yunjisuan.com;
location / {
proxy_pass http://default_server;
proxy_set_header host $host;
proxy_set_header x-forward-for $remote_addr;
include proxy.conf; #proxy.conf檔案中包含優化的引數
}
}
}
[[email protected] conf]# vim 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;

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

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

下圖為企業常見的動靜分離叢集架構圖,此架構圖適合網站前端只使用同一個域名提供服務的場景,例如,使用者訪問的域名是www.yunjisuan.com,然後,當用戶請求www.yunjisuan.com/upload/xx地址時候,代理會分配請求到上傳伺服器池處理資料;當用戶請求www.yunjisuan.com/static/xx地址的時候,代理會分配請求到靜態伺服器池請求資料;當用戶請求www.yunjisuan.com/xx地址的時候,即不包含上述指定的目錄地址路徑時,代理會分配請求到預設的動態伺服器池請求資料(注意:上面的xx表示任意路徑)。
上傳伺服器需要掛載NFS共享儲存;動態伺服器無需掛載NFS共享儲存,因為瀏覽器解析該文字內容,題目文字直接解析到了瀏覽器上,當遇到圖片的時候,瀏覽器順著圖片的連結直接去讀取圖片。
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181130124941359.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
先進行企業案例需求梳理:

當用戶請求www.yunjisuan.com/upload/xx地址時,實現由upload上傳伺服器池處理請求。
當用戶請求www.yunjisuan.com/static/xx地址時,實現由靜態伺服器池處理請求。
除此以外,對於其他訪問請求,全都由預設的動態伺服器池處理請求。
瞭解了需求後,就可以進行upstream模組伺服器池的配置了。
同時,當用戶訪問動態頁面(圖片)時,跳轉到static下的圖片。

環境部署
nginx伺服器 192.168.239.129
web01節點 192.168.239.130 static_server
web02節點 192.168.239.131 upload_server
web03節點 192.168.239.128 default_server

1.nginx伺服器

```
[[email protected] html]# cd /usr/local/nginx/conf/
[[email protected] conf]# vim 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_server {
server 192.168.239.130;
}
upstream upload_server {
server 192.168.239.131;
}
upstream default_server{
server 192.168.239.128;
}
server {
listen 80;
server_name www.yunjisuan.com;
location /static/ {
proxy_pass http://static_server;
include proxy.conf;
}
location /upload/ {
proxy_pass http://upload_server;
include proxy.conf;
}
location / {
proxy_pass http://default_server;
include proxy.conf;
}
}
}
[[email protected] conf]# vim 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;
[[email protected] conf]# /usr/local/nginx/sbin/nginx -s reload

```
2. web服務端的部署

```
[[email protected] conf]# vim 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"' #來源IP、來源使用者、時間、請求
'$status $body_bytes_sent "$http_referer"' #狀態碼、主體(顯示傳送的大小)、來源瀏覽器、使用者客戶端、使用者的IP
'"$http_user_agent""$http_x_forwarded_for"'; #日誌格式化,節點伺服器需要的訪問日誌如果要記錄使用者的真實IP,還必須進行日誌格式配置,這樣才能把代理傳過來的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; #啟用日誌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;
}
}
[[email protected] conf]# /usr/local/nginx/sbin/nginx
[[email protected] conf]# netstat -antup | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx
[[email protected] nginx]# mkdir /usr/local/nginx/html/{www,bbs}
[[email protected] nginx]# echo "`hostname -I `www" >> /usr/local/nginx/html/www/index.html
[[email protected] nginx]# cat /usr/local/nginx/html/www/index.html
192.168.239.130 www
[[email protected] nginx]# echo "`hostname -I `bbs" >> /usr/local/nginx/html/bbs/index.html
[[email protected] nginx]# cat /usr/local/nginx/html/bbs/index.html
192.168.239.130 bbs
[[email protected] conf]# vim /etc/hosts
192.168.239.130 www.yunjisuan.com bbs.yunjisuan.com
[[email protected] conf]# curl www.yunjisuan.com
192.168.239.130 www
[[email protected]host conf]# curl bbs.yunjisuan.com
192.168.239.130 bbs

# web02、web03同上操作
```
3.web01中建立static目錄,並插入圖片
```
[[email protected] conf]# cd /usr/local/nginx/html/www/
[[email protected] www]# mkdir static
[[email protected] www]# echo "static_pools" >> static/index.html
[[email protected] www]# curl http://www.yunjisuan.com/static/index.html #這裡的www.yunjisuan.com是解析過的Web01的本地IP
static_pools
[[email protected] static]# ls
111.jpeg index.html # 在靜態池web01中加入圖片

```
4. web02中建立upload目錄,並測試

```
[[email protected] ~]# cd /usr/local/nginx/html/www/
[[email protected] www]# mkdir upload
[[email protected] www]# echo "upload_pools" >> upload/index.html
[[email protected] www]# curl http://www.yunjisuan.com/upload/index.html #這裡的www.yunjisuan.com是解析過的Web02的本地IP
upload_pools
```
5. web03動態服務節點,新增圖片訪問路徑

```
[[email protected] www]# cd /usr/local/nginx/html/www
[[email protected] www]# vim index.html
default_pools
<img src="http://192.168.239.129/static/111.jpeg" > #反向代理的IP地址
[[email protected] www]# curl http://www.yunjisuan.com
default_pools
<img src="http://192.168.239.130/static/111.jpeg" >

```
6. 測試訪問圖片
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181130230135822.)

![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181130230209596.)

==其中,location語句可以通過以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;

}
```

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

##### 根據客戶端的裝置(user_agent)轉發實踐需求
(1)常規4層負載均衡解決方案架構

在常規4層負載均衡架構下,可以使用不同的域名來實現這個需求,例如,人為分配好讓移動端使用者訪問wap.yunjisuan.com,PC客戶端使用者訪問www.yunjisuan.com,通過不同域名來引導使用者到指定的後端伺服器,該解決方案的架構圖如下:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181130233748519.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
此解決方案的最大問題就是不同客戶端的使用者要記住對應的域名!而絕大多數使用者只會記住www.yunjisuan.com,不會記住wap.yunjisuan.com,這樣一來就會導致使用者體驗不是很好。有沒有辦法讓所有客戶端使用者只訪問一個統一的www.yunjisuan.com這個地址,還能讓不同客戶端裝置都能有更好的訪問體驗呢?當然有!那就是下面的第7層負載均衡解決方案。

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

在第7層負載均衡架構下,就可以不需要人為拆分域名了,對外只需要用一個域名,例如www.yunjisuan.com,通過獲取使用者請求中的裝置資訊(利用$http_user_agent獲取),根據這些資訊轉給後端合適的伺服器處理,這個方案最大好處就是不需要讓使用者記憶多個域名了,使用者只需要記住主網站地址www.yunjisuan.com,剩下的由網站伺服器處理,這樣的思路大大地提升了使用者訪問體驗,這是當前企業網站非常常用的解決方案。
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181130233810509.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)

```
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;
}
```
##### 根據副檔名實現代理轉發
除了根據URI路徑及user_agent轉發外,還可以實現根據副檔名進行轉發
相關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;

}
```
根據副檔名轉發的應用場景
可根據副檔名實現資源的動靜分離訪問,如圖片,視訊等請求靜態伺服器池,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

}
```
在開發無法通過程式實現動靜分離的時候,運維可以根據資源實體進行動靜分離,而不依賴於開發,具體實現策略是先把後端的伺服器分成不同的組。注意,每組伺服器的程式都是相同的,因為開發沒有把程式拆開,分組後,在前端代理伺服器上通過講解過的路徑,副檔名進行規則匹配,從而實現請求的動靜分離。
##### 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軟體
[[email protected] ~]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.10.2

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

#因為是對源程式打補丁,所以還需要Nginx源程式
[[email protected] ~]# cd /usr/src/nginx-1.10.2/
[[email protected] 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

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

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

[[email protected] 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/
[[email protected] 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的安裝目錄下
[[email protected] local]# pwd
/usr/local
[[email protected] local]# cp nginx.ori/conf/nginx.conf nginx/conf/
cp: overwrite `nginx/conf/nginx.conf'? y
[[email protected] local]# cp nginx.ori/conf/proxy.conf nginx/conf/
[[email protected] 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健康檢查

```
[[email protected] 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服務

```
[[email protected] local]# /usr/local/nginx/sbin/nginx
[[email protected] 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
訪問頁面時,顯示如下圖所示:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2018120100270811.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
在lb1配置檔案的upstream default_pools{}裡也加入健康監測命令

```
[[email protected] 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的訪問日誌記錄

}

}
}
```
再次訪問健康監測頁面時,顯示如下圖所示:
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20181201002743588.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
關閉任意一個RS節點後(3個Web伺服器任選一個關閉nginx服務)

```
#關閉Web02的nginx服務
[[email protected] ~]# /usr/local/nginx/sbin/nginx -s stop
```
再次訪問健康監測頁面時,顯示如下圖所示:

![在這裡插入圖片描述](https://img-blog.csdnimg.cn/201812010028157.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
#### 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; #表示如果在反向代理給某一個伺服器池的時候,返回報頭出現error、timeout、無效報頭、500、502、503、504時,不返回給使用者,而是在進行一次反向代理。
include proxy.conf;

}

}
```