說到負載均衡,我想說它天生就是不公平的。為什麼這麼說呢?請你想象這麼一個場景,一塊蛋糕切成5份,現在要將它分給A、B、C3個人,基於公平原則,我們說每個人正常可以分到5/3份,但是,5/3份很明顯不好進行劃分,誒碰巧這個時候A中午沒有吃飯,能多吃幾份,B、C肚子偏飽,1份即可,基於不公平原則,我們分給A3份蛋糕,B、C個一份,這樣按照一定策略將資源進行劃分的方式,是一種均衡的策略。
在web應用中,一個web應用(或者說某個服務)在生產環境中一般是叢集部署,然後採用負載均衡硬體(F5)或者軟體(nginx)將請求分發到不同的服務主機中進行處理,很明顯,這裡的蛋糕就相當於我們的web request,假設有5個request進來,基於一定的均衡策略,我們可能會將其中的3個request交給A伺服器去處理,B、C伺服器各處理1個request。下面我畫張圖片簡單說明這個模型:
那麼使用負載均衡有什麼好處呢?首先優化資源利用率,最大化吞吐量,減少延遲,再者系統的伸縮性和可靠性也得到了相應的保障。
一、Nginx 負載均衡及相關策略介紹
負載均衡技術少不了相關的均衡策略,Nginx 中提供了 4 種均衡策略,我們可以根據具體的業務場景選擇合適的均衡策略。下面分別介紹這 4 中均衡策略:
-
1、基於輪詢的均衡策略:
輪詢嘛,就是說對進到nginx的request按照遍歷的方式進行分發,如果request 1 分發到 Server A,那麼request 2將被分發到 Server B,……以此迴圈類推
-
2、基於最少連線數的均衡策略:
最少連線,也就是說nginx會判斷後端叢集伺服器中哪個Server當前的 Active Connection 數是最少的,那麼對於每個新進來的request,nginx將該request分發給對應的Server.
-
3、基於ip-hash的均衡策略:
我們都知道,每個請求的客戶端都有相應的ip地址,該均衡策略中,nginx將會根據相應的hash函式,對每個請求的ip作為關鍵字,得到的hash值將會決定將請求分發給相應Server進行處理
-
4、基於加權輪詢的均衡策略:
加權輪詢,很顯然這個策略跟我們開題引入的場景是一樣的,nginx會給Server配置相應的權重,權重越大,接收的request數將會越多
上面的均衡策略其實都非常很好理解,但是如果想了解其實現原理,可以看原始碼,但是小編就算了,我是看不懂C、C++的。
二、Nginx 不同均衡策略的配置介紹
- 1、基於輪詢的均衡策略:
這個是Nginx預設的均衡演算法,如果你不進行相關的配置,預設會執行該策略,配置如下:
http {
upstream myapp1 {
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
} server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}
}複製程式碼
可以看出,nginx負載均衡使用到的指令不多,其中比較重要的兩個是upstream
和proxy_pass
,upstream
塊定義一個後端小叢集,裡邊配置相關的Server組成這個叢集,同時upstream
為這個叢集起個相應的名字,本例項叫myapp1
.proxy_pass
處於location
塊中,表示對於所有符合/
的request,將會交給哪個叢集進行處理,本例項為http://myapp1
。
但又一點我們需要注意,上面http://myapp1
中myapp1
必須是upstream
起的名字,對於協議是使用http
還是https
,都無所謂,如果你的協議使用https
,則將http
直接改成https
即可。另外,如果你在upstream
中的server
指令中指定了協議名,那麼在proxy_pass
指令中就不需要加上協議名稱了。
nginx負載均衡使用反向代理實現,也就是我們上面使用到的proxy_pass
指令,支援的協議不止是http
和https
,同時還支援FastCGI
、uwsgi
、SCGI
、memcached
、gRPC
,如果你需要使用除了http
、https
外的其他協議,我們不能使用proxy_pass
指令了,應該轉而使用相應的指令,如fastcgi_pass
、uwsgi_pass
、scgi_pass
、memcached_pass
、grpc_pass
。
該策略處理負載,小編認為還是有缺陷的,不能防止某臺Server出現負載過高的情況。因為如果有些請求執行時間過長,而系統的併發量卻非常大,那麼就可能導致某臺Server出現request堆積,負載過高,snowslide is possible~
- 2、基於最少連線數的均衡策略:
該策略主要使用了least_conn
指令,具體配置如下:
upstream myapp1 {
least_conn;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}複製程式碼
該策略還是比較人性化的,可以按照機器的實際情況進行剛需分配。
- 3、基於ip-hash的均衡策略:
當然了,如果我們想實現這樣一個功能,我們想讓對於相同客戶端的請求每次都被分發到同一個Server進行處理,上面兩種策略都是不做到。此策略可確保來自同一客戶端的請求始終定向到同一伺服器,但此伺服器不可用時除外。相關配置如下:
upstream myapp1 {
ip_hash;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}複製程式碼
既然相同客戶端的請求能被同一臺Server進行處理,那麼相同客戶端的會話Session就可以實現持久化了。
- 4、基於加權輪詢的均衡策略:
基於加權輪詢的策略就不需要過多講解了,就是在輪詢的基礎上加上個權重資訊
upstream myapp1 {
server srv1.example.com weight=3;
server srv2.example.com;
server srv3.example.com;
}複製程式碼
這種策略適合Server機器處理能力有區別的情況。
三、nginx 負載均衡更多高階特性及配置
-
1、健康檢查
不僅人需要體檢,機器也是需要體檢的,那麼就當nginx就是那位體檢醫生吧!nginx健康檢查是什麼呢?當我們一個request進來被分發到相應的Server進行處理後,nginx會檢查該request執行是否超時,是否執行失敗了等情況,然後做出相應的處理—比如說當nginx檢查出Server A執行某request時報出502錯誤了,那麼下次nginx負載均衡時就會在
upstream
塊中將Server A排除掉,不分發請求給到Server A了。對於健康檢查的功能,nginx提供了基本兩個指令,即
max_fails
和fail_timeout
,也就是說當nginx檢查到某Server發生錯誤的request數達到max_fails
或者執行某request執行時間超過fail_timeout
了,如果發生超時了,nginx將開始使用實時請求優雅地探測Server,如果有響應,則認為對應的Server還是活著的,沒有毛病的。 -
2、更多配置
針對上面
upstream
塊中的server
指令,其格式為:server address [parameters];
,裡邊的parameters
可以有很多的引數型別,比如說指定某臺Server不參與負載均衡等。具體配置詳見官網連結,點選此處傳送門。