1. 程式人生 > >Nginx 學習 —— 負載均衡

Nginx 學習 —— 負載均衡

擁抱心中的夢想 芋道原始碼 3天前 點選上方“芋道原始碼”,選擇“置頂公眾號”

技術文章第一時間送達!

原始碼精品專欄

精盡 Dubbo 原理與原始碼 69 篇

精盡 Netty 原理與原始碼 61 篇

中文詳細註釋的開源專案

Java 併發原始碼合集

RocketMQ 原始碼合集

Sharding-JDBC 原始碼解析合集

Spring MVC 和 Security 原始碼合集

MyCAT 原始碼解析合集

說到負載均衡,我想說它天生就是不公平的。為什麼這麼說呢?請你想象這麼一個場景,一塊蛋糕切成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、基於加權輪詢的均衡策略:

基於加權輪詢的策略就不需要過多講解了,就是在輪詢的基礎上加上個權重資訊

三、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不參與負載均衡等。具體配置詳見官網連結,點選此處傳送門。

如果你對 Dubbo / Netty 等等原始碼與原理感興趣,歡迎加入我的知識星球一起交流。長按下方二維碼噢:

目前在知識星球更新了《Dubbo 原始碼解析》目錄如下:

  1. 除錯環境搭建

  2. 專案結構一覽

  3. 配置 Configuration

  4. 核心流程一覽

  5. 拓展機制 SPI

  6. 執行緒池

  7. 服務暴露 Export

  8. 服務引用 Refer

  9. 註冊中心 Registry

  10. 動態編譯 Compile

  11. 動態代理 Proxy

  12. 服務呼叫 Invoke

  13. 呼叫特性

  14. 過濾器 Filter

  15. NIO 伺服器

  16. P2P 伺服器

  17. HTTP 伺服器

  18. 序列化 Serialization

  19. 叢集容錯 Cluster

  20. 優雅停機

  21. 日誌適配

  22. 狀態檢查

  23. 監控中心 Monitor

  24. 管理中心 Admin

  25. 運維命令 QOS

  26. 鏈路追蹤 Tracing

… 一共 69+ 篇

目前在知識星球更新了《Netty 原始碼解析》目錄如下:

  1. 除錯環境搭建

  2. NIO 基礎

  3. Netty 簡介

  4. 啟動 Bootstrap

  5. 事件輪詢 EventLoop

  6. 通道管道 ChannelPipeline

  7. 通道 Channel

  8. 位元組緩衝區 ByteBuf

  9. 通道處理器 ChannelHandler

  10. 編解碼 Codec

  11. 工具類 Util

… 一共 61+ 篇

目前在知識星球更新了《資料庫實體設計》目錄如下:

  1. 商品模組
  2. 交易模組
  3. 營銷模組
  4. 公用模組

… 一共 17+ 篇