nginx 反向代理實現負載均衡理論
Nginx負載均衡集群介紹
負載均衡集群提供了一種廉價,有效,透明的方法,來擴展網絡設備和服務器的負載,帶寬和吞吐量,同時加強了網絡數據處理能力,提高了網絡的靈活性和可用性。
搭建負載均衡服務的需求:
(1)把單臺計算機無法承受的大規模並發訪問或數據流量分擔到多臺節點設備上,分別進行處理,減少用戶等待響應的時間,提升用戶體驗。
(2)單個重負載的運算分擔到多臺節點設備上做並行處理,每個節點設備處理結束後,將結果匯總,返回給用戶,系統處理能力得到大幅度提高。
(3)7*24小時的服務保證,任意一個或多個有限後面節點設備宕機,不能影響業務。
反向代理與負載均衡概念簡介:
Nginx僅僅是作為Nginx Proxy反向代理使用的,因為這個反向代理功能表現的效果是負載均衡集群的效果,所以稱之為Nginx負載均衡
反向代理接收訪問用戶的請求後,會代理用戶重新發起請求代理下的節點服務器,最後把數據返回給客戶端用戶,在節點服務器看來,訪問的節點服務器的客戶端用戶就是反向代理服務器了,而非真實的網站訪問用戶。Nginx反向代理是接收用戶的請求然後重新發起請求去請求其後面的節點。
實現Nginx負載均衡的組件說明:
搭載nginx負載均衡
實驗環境:
服務器 | IP | 說明 |
lb160 | 192.168.50.160 | 主nginx負載均衡 |
lb162 | 192.168.50.162 | 備nginx負載均衡 |
nginx163 | 192.168.50.163 | nginx服務1 |
nginx164 | 192.168.50.164 | nginx服務2 |
軟件準備
系統:CentOS Linux release 7.5.1804 (Core) (不了解CentOS7看前邊CentOS7博文)
軟件:nginx-1.14.0.tar.gz
安裝Nginx軟件
4臺服務器安裝Nginx
yum install -y pcre-devel openssl-devel gcc gcc-c++ make #安裝依賴包命令 useradd -s /sbin/nologin -M nginx #創建用戶 tar xf nginx-1.14.0.tar.gz -C /usr/src/ #tar解壓 cd /usr/src/nginx-1.14.0/ ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module ; make ; make install ln -s /usr/local/nginx/sbin/* /usr/local/sbin/ #軟連接到全局變量
Centos7 system啟動nginx文件
vim /usr/lib/systemd/system/nginx.service #創建nginx.service文件 插入下邊代碼
[Unit] Description=The NGINX HTTP and reverse proxy server After=syslog.target network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/usr/local/nginx/logs/nginx.pid ExecStartPre=/usr/local/nginx/sbin/nginx -t ExecStart=/usr/local/nginx/sbin/nginx ExecReload=/usr/local/nginx/sbin/nginx -s reload ExecStop=/usr/bin/kill -s QUIT $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target
將啟動腳本發給其他三臺服務器
scp /usr/lib/systemd/system/nginx.service root@192.168.50.162:/usr/lib/systemd/system/ scp /usr/lib/systemd/system/nginx.service root@192.168.50.163:/usr/lib/systemd/system/ scp /usr/lib/systemd/system/nginx.service root@192.168.50.164:/usr/lib/systemd/system/
配置用於測試的Web服務
nginx163 測試配置文件
vim /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"‘; server { listen 80; server_name bbs.wk.com; location / { root html/bbs; index index.html index.htm; } access_log logs/access_bbs.log main; } server { listen 80; server_name www.wk.com; location / { root html/www; index index.html index.htm; } access_log logs/access_www.log main; } }
#提示:
這裏故意將www虛擬主機放在下面,便於用後面的參數配置測試效果
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
nginx #啟動服務
加入測試數據文件
mkdir /usr/local/nginx/html/{www,bbs} echo "111111111111111" >> /usr/local/nginx/html/www/index.html echo "222222222222222" >> /usr/local/nginx/html/bbs/index.html 開啟服務後自己做測試看是否能訪問
nginx164 測試配置文件
vim /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"‘; server { listen 80; server_name www.wk.com; location / { root html/www; index index.html index.htm; } access_log logs/access_www.log main; } server { listen 80; server_name bbs.wk.com; location / { root html/bbs; index index.html index.htm; } access_log logs/access_bbs.log main; } }
mkdir /usr/local/nginx/html/{www,bbs}
echo "wwwwwwwwww" >> /usr/local/nginx/html/www/index.html
echo "bbbbbbbbbb" >> /usr/local/nginx/html/bbs/index.html
提示:
(1)不同Web測試節點,返回的結果是不同的,這是為了方便測試演示!
(2)通過上面配置就實現了兩臺Web服務器基於域名的虛擬主機配置。
實現一個簡單的負載均衡
配置lb160配置文件
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服務器池,包含了163,164兩個Web節點 server 192.168.50.163:80 weight=1; server 192.168.50.164:80 weight=1; } server { #這裏定義代理的負載均衡域名虛擬主機 listen 80; server_name www.wk.com; location / { proxy_pass http://www_server_pools; #訪問www.wk.com,請求發送給www_server_pools裏面的節點 } } } #幹凈網頁 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.50.163:80 weight=1; server 192.168.50.164:80 weight=1; } server { listen 80; server_name www.wk.com; location / { proxy_pass http://www_server_pools; } } }
檢查語法並啟動並在網頁上測試
hosts域名解析
兩個Web節點按照1:1的比例被訪問,宕掉任意一個Web節點,網站業務不受影響,訪問請求都定位到了正常的節點上
從新開啟會又安1:1比例被訪問
Nginx負載均衡核心組件介紹
Nginx upstream模塊
Nginx upstream模塊
Nginx的負載均衡功能依賴於ngx_http_upsteam_module模塊,所支持的代理方式包括proxy_pass,fastcgi_pass,memcached_pass等,新版Nginx軟件支持的方式有所增加。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
upstream模塊語法
範例1:基本的upstream配置案例
upstream www_server_pools { #upstream是關鍵字必須有,後面的www_server_pools為一個Upstream集群組的名字,可以自己起名,調用時就用這個名字 server 192.168.50.163:80 weight=5; server 192.168.50.164:80 weight=10; server 192.168.50.165:80 weight=15; #server關鍵字是固定的,後面可以接域名(門戶會用)或IP。如果不指定端口,默認是80端口。weight代表權重,
數值越大被分配的請求越多,結尾有分號,別忘了。 }
範例2:較完整的upstream配置案例
upstream blog_server_pool { server 192.168.50.163; #這行標簽和下行是等價的 server 192.168.50.164:80 weight=1 max_fails=1 fail_timeout=10s; #這行標簽和上一行是等價的,此行多余的部分就是默認配置,不寫也可以。 server 192.168.50.165: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.50.163; server 192.168.50.164:8080; server backup1.example.com:8080 backup; #備份服務器,等上面指定的服務器都不可訪問的時候會啟動,backup的用法和Haproxy中用法一樣 server backup2.example.com:8080 backup; }
如果是兩臺Web服務器做高可用,常規方案就需要keepalived配合,那麽這裏使用Nginx的backup參數通過負載均衡功能就可以實現Web服務器集群了,對於企業應用來說,能做集群就不做高可用。
upstream模塊相關說明
upstream模塊的內容應放於nginx.conf配置的http{}標簽內,其默認調度節點算法是wrr(weighted round-robin,即權重輪詢)。
upstream模塊內參數 | 參數說明 |
server 192.168.50.163 | 負載均衡後面的RS配置,可以是IP或域名,如果端口不寫,默認是80端口。高並發場景下,IP 可換成域名,通過DNS做負載均衡 |
weight=1 | 代表服務器的權重,默認值是1。權重數字越大表示接受的請求比例越大 |
max_ fails=1 |
Nginx嘗試連接後端主機失敗的次數,這個數值是配合proxy_ next_ upstream,fastcgi_ next_ upstream 和memcached_ next_ upstream |
backup |
熱備配置(RS節點的高可用),當前面激活的RS都失敗後會自動啟用熱備RS。這標誌著這個服務器作為備份服務器,若主服務器全部宕機了,就會向它轉發請求;註意,當負載調度算法為ip_hash時,後端服務器在負載均衡調度中的狀態不能是weight和backup |
fail_timeout=10s |
在max_fails定義的失敗次數後,距離下次檢查的間隔時間,默認是10s;如果max_ fails是5,它就檢測5次, 如果5次都是502。那麽,它就會根據fail_ timeout的值,等待10s再去檢查,還是只檢查一-次, 如果持續502,在不重新加載Nginx配置的情況“下,每隔10s都只檢測一次。常規業務2 ~ 3秒比較合理,比如京東3秒,藍汛3秒,可根據業務需求去配置 |
down |
這標誌著服務器永遠不可用,這個參數可配合ip_ hash 使用 |
示例,如下:
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.50.163:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2 server php_server_2 192.168.50.164:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1 server php_server_bak 192.168.50.165:80 cookie 3 check inter 1500 rise 3 fall 3 backup
上述命令的說明如下:
- weight:調節服務器的請求分配權重。
- check:開啟對該服務器健康檢查。
- inter:設置連續兩次的健康檢查間隔時間,單位毫秒,默認值2000
- rise:指定多少次連續成功的健康檢查後,即可認定該服務器處於可用狀態。
- fall:指定多少次不成功的健康檢查後,即認為服務器為宕機狀態,默認值3.
- maxconn:指定可被發送到該服務器的最大並發連接數。
upstream模塊調度算法
調度算法一般分為兩類:
第一類為靜態調度算法,即負載均衡器根據自身設定的規則進行分配,不需要考慮後端節點服務器的情況,例如:rr,wrr,ip_hash等都屬於靜態調度算法。
第二類為動態調度算法,即負載均衡器會根據後端節點的當前狀態來決定是否分發請求,例如:連接數少的優先獲得請求,響應時間短的優先獲得請求。例如:least_conn,fair等都屬於動態調度算法。
常見的調度算法。
rr輪詢(默認調度算法,靜態調度算法)
wrr(權重輪詢,靜態調度算法)
ip_hash(靜態調度算法)(會話保持)
每個請求按客戶端IP的hash結果分配,當新的請求到達時,先將其客戶端IP通過哈希算法哈希出一個值,在隨後的客戶端請求中,客戶IP的哈希值只要相同,就會被分配至同一臺服務器,該調度算法可以解決動態網頁的session共享問題,但有時會導致請求分配不均,即無法保證1:1的負載均衡,因為在國內大多數公司都是NAT上網模式,多個客戶端會對應一個外部IP,所以,這些客戶端都會被分配到同一節點服務器,從而導致請求分配不均。LVS負載均衡的-p參數,Keepalived配置裏的persistence_timeout 50參數都類似這個Nginx裏的ip_hash參數,其功能都可以解決動態網頁的session共享問題。
示例如下:
upstream { ip_hash; server 192.168.50.163:80; server 192.168.50.164: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,即使有也不會生效。
fair(動態調度算法)
此算法會根據後端節點服務器的響應時間來分配請求,響應時間短的優先分配。這是更加智能的調度算法。此種算法可以根據頁面大小和加載時間長短智能地進行負載均衡,也就是根據後端服務器的響應時間來分配請求,響應時間短的優先分配。Nginx本身不支持fair調度算法,如果需要使用這種調度算法,必須下載Nginx相關模塊upstream_fair。
示例如下:
upstream yunjisuan_lb{ server 192.168.50.163; server 192.168.50.164; fair; }
least_conn
least_conn算法會根據後端節點的連接數來決定分配情況,哪個機器連接數少就分發。
除了上面介紹的這些算法外,還有一些第三方調度算法,例如:url_hash,一致性hash算法等,介紹如下。
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; }
一致性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
http_proxy_module模塊
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的使用案例:
將匹配URI為name的請求拋給http://127.0.0.1/remote/.
location /name/ { proxy_pass http://127.0.0.1/remote/; }
將匹配URI為some/path的請求拋給http://127.0.0.1 location /some/path/ { proxy_pass http://127.0.0.1; }
將匹配URI為name的請求應用指定的rewrite規則,然後拋給http://127.0.0.1 location /name/ { rewrite /name/( [^/]+ ) /username=$1 break; proxy_pass http://127.0.0.1; }
http proxy模塊參數
Nginx的代理功能是通過http proxy模塊來實現的。默認在安裝Nginx時已經安裝了http proxy模塊,因此可直接使用http proxy模塊。下面詳細解釋模塊1中每個選項代表的含義,見下表:
http proxy模塊相關參數 | 說明 |
proxy_ set_ header | 設置http請求header項傳給後端服務器節點,例如:可實現讓代理後端的服務器節點獲取訪問客戶端用戶的真實IP地址 |
client_ body_ buffer_ size | 用於指定客戶喘請求主體緩沖區大小,此處如了解前文的http請求包的原理就好理解了 |
proxy_ connect_ timeout | 表示反向代理與後端節點服務器連接的超時時間,即發起握手等候響應的超時時間 |
proxy_ send_ timeout | 表示代理後端服務器的數據回傳時間,即在規定時間之內後端服務器必須傳完所有的數據,否則,Nginx將斷開這個連接 |
proxy_ read_ timeout | 設置Nginx從代理的後端服務器獲取信息的時間,表示連接建立成功後,Nginx等待後端服務器的響應時間,其實是Nginx已經進人後端的排隊之中等候處理的時間 |
proxy_ buffer_ size | 設置緩沖區大小,默認該緩沖區大小等於指令proxy_ buffers 設置的大小 |
proxy_ buffers | 設置緩沖區的數量和大小。Nginx 從代理的後端服務器獲取的響應信息,會放置到緩沖區 |
proxy_ busy_ buffers_ size | 用於設置系統很忙時可以使用的proxy_buffers大小,官方推薦的大小為proxy_ buffers*2 |
proxy_ temp_ file_ write_ size | 指定proxy緩存臨時文件的大小 |
nginx 反向代理實現負載均衡理論