Nginx的負載均衡

  • 2019 年 10 月 3 日
  • 筆記

我們都知道,Nginx支援負載均衡,可以很方便的幫助我們進行水平擴容,然而它究竟是依據什麼原則進行請求的分發,其中又有哪些負載均衡演算法可供選擇和配置,今天就讓我們好好來了解一下。

負載均衡的定義

什麼叫負載均衡,我們可以參考一下圖片中的這種情況:

  1. 當客戶端發送請求時,會先到Nginx,然後Nginx會將請求分發到後台不同的伺服器上。
  2. 如果後台的伺服器群中有一個宕機了,那麼Nginx會自動忽略這台伺服器,不會將請求再次分發到這台伺服器上。
  3. 如果有新加入的伺服器,Nginx也會將請求分發到這台伺服器上。

我所理解的負載均衡,就是:

能夠將客戶端的請求均勻地分發到後台各個應用伺服器上,從而緩解伺服器壓力。

並且當伺服器出現宕機或者擴容時,也能正常運行。

負載均衡的方法

上面了解了什麼是負載均衡,那麼Nginx是怎麼實現這個功能的呢?

upstream和server的使用

Nginx中負責與上游交互的模組,統稱為upstream模組。

而指定上游服務地址是通過upstream和server指令完成的,其關係為:

指定上游伺服器的address時,其地址可以是域名、IP地址或者unix socket地址。

可以在域名或者IP地址後加埠,如果不加埠,那麼默認使用80埠。

在address後面可以添加一些參數,比如:

backup:指定當前server為備份服務,僅當非備份server不可用時,請求才會轉發到該server。

down:標識某台服務已經下線,不再服務。

舉個例子:

    upstream upstream-service {          server 127.0.0.1:17002;          server 127.0.0.1:17000;      }

round-robin

在upstream這個模組中,它還提供了一個最基本的負載均衡演算法round-robin。

其功能是:

以加權輪詢的方式訪問server指令指定的上游服務。

這個演算法是默認集成在Nginx的框架中,無法移除,所以後面講解的所有演算法都是基於此,所有演算法在某些特殊情況下最終都會變成round-robin。

涉及到的指令有:

  1. weight:服務訪問的權重,默認是1。
  2. max_conns:server的最大並發連接數,僅作用於單worker進程。
  3. max_fails:在fail_timeout時間內,最大的失敗次數。當達到最大失敗時,會在fail_timeout時間內不允許再次被選擇。
  4. fail_timeout:單位為秒,默認是10秒。指定一段時間內,最大的失敗次數max_fails。到達max_fails後,該server不能訪問的時間。

簡單的hash模組

有的時候,正常的輪詢演算法並不能滿足我們的需求,

比如:帶有cookie請求狀態的連接,如果應用服務沒有設置專門的管理cookie的伺服器,那麼我們就希望同一個用戶能被分配到同一個伺服器。

再比如:我們後端應用需要針對請求當中的參數或者URL,將相同的請求放到相同的伺服器上進行處理。

針對第一種情況,就可以用upstream_ip_hash。針對第二種情況,可以使用upstream_hash。

upstream_ip_hash

功能:

以客戶端的IP地址作為hash演算法的關鍵字,映射到特定的上游伺服器中。

  1. 對IPV4地址使用前3個位元組作為關鍵字,對IPV6則使用完整地址。
  2. 可以使用round-robin演算法的參數。
  3. 可以基於realip模組修改用於執行演算法的IP地址。

舉個例子:

    upstream upstream-service {          ip_hash;          server 127.0.0.1:17002;          server 127.0.0.1:17000;      }

upstream_hash

功能:

通過制定關鍵字作為hash key,基於hash演算法映射到特定的上游伺服器中。

  1. 關鍵字可以含有變數、字元串。
  2. 可以使用round-robin演算法的參數。

舉個例子(以請求中的參數username作為hash key):

    upstream upstream-service {          hash user_$arg_username;          server 127.0.0.1:17002;          server 127.0.0.1:17000;      }

一致性哈希演算法

hash演算法在一定程度上已經可以滿足了我們的業務需求,但如果這個時候遇到應用宕機或者應用擴容,那麼hash的總數就會變化,這樣很有可能帶來大量請求原本請求的伺服器會更換,路由會失效,這樣對於我們的應用服務也會產生極大的影響,這時候就可以採用一致性hash演算法。

對於一致性哈希演算法的理解,可以參考這篇文章:一致性哈希演算法的理解與實踐

它的使用也十分簡單,就是在之前說的upstream_hash模組的hash指令最後,添加參數consistent,這樣Nginx就可以使用一致性哈希演算法了。

舉個例子(仍以請求中的參數username作為hash key):

    upstream upstream-service {          hash user_$arg_username consistent;          server 127.0.0.1:17002;          server 127.0.0.1:17000;      }

總結

以上就是Nginx中比較常見的負載均衡方法了,還有一些比如最少連接演算法等,都是在此之上的一些應用。如果大家有什麼疑問,歡迎在下方留言。

有興趣的話可以訪問我的部落格或者關注我的公眾號、頭條號,說不定會有意外的驚喜。

https://death00.github.io/

Tags: