Nginx 開發與操作 - HTTP 負載均衡 介紹 HTTP 負載均衡的內部機制。

Published on Friday, July 19, 2024

在第一篇的文章中,學習到 如何使用 Play with Docker 建構一個 Nginx 開發環境,還有進行簡單的測試。


Round-Robin(Default)

今天要學習 HTTP 負載均衡內部的內部機制了解 Nginx 是怎麼進行請求分配的。 首先複習一下昨天的設定檔:

upstream node {
      server 192.168.0.17:80;
      server 192.168.0.16:80;
}
server {
      listen 80 default_server;
      listen [::]:80 default_server;
      
      location / {
          proxy_pass http://node;
      }
}

在這分設定檔中我們設定了一個 Server Group 名稱為 node,在這邊我們只有設定兩台伺服器並沒有設定分配方法,所以會預設使用 round-robin 方法來分配每一個請求,這也是昨天我們測試時每次按下重新整理伺服器會循環切換的原因。


Least Connected

當某些需要長時間執行請求可以選擇 Least Connected 方法來分配請求,Least connected 會檢查目前 Server Group 內部的伺服器找出連線數量 最低的那一台機器並分配給它。

要使用 Least Connected 方法需要額外在 upstream 添加 least_conn 命令。

upstream node {
      least_conn;
      server 192.168.0.17:80;
      server 192.168.0.16:80;
}
server {
      listen 80 default_server;
      listen [::]:80 default_server;
      
      location / {
          proxy_pass http://node;
      }
}

IP Hash

前兩種分配請求的方式都是無狀態的,代表之後同一個客戶端發出的每次請求都不會轉發到同一台伺服器上,這樣第一次連線的伺服器所建立的緩存就沒辦法生效, 這種時候可以改用 IP Hash 方法,IP Hash 方法會在分配請求前將客戶端的 IP 進行 Hash 計算這樣就能得出一個固定的值,所以之後的請求就能一直轉發到 同一台伺服器上。

要使用 IP Hash 方法需要額外在 upstream 添加 ip_hash 命令。

upstream node {
      ip_hash;
      server 192.168.0.17:80;
      server 192.168.0.16:80;
}
server {
      listen 80 default_server;
      listen [::]:80 default_server;
      
      location / {
          proxy_pass http://node;
      }
}

Least Time(商業版)

least_timeleast_conn 命令類似,不過 least_time 會參考 Server Group 裡每台伺服器的請求回應時間,並將請求轉發給執行時間 最短的伺服器上,least_time 可以算是優化過後的 least_conn 不過要決定哪一台伺服器執行請求的時間是最短的,還需要額外搭配幾個參數 headerlast_byteinflight(可選)

使用 least_time 的設定檔會有以下內容

upstream node {
      least_time header inflight;
      server 192.168.0.17:80;
      server 192.168.0.16:80;
}
server {
      listen 80 default_server;
      listen [::]:80 default_server;
      
      location / {
          proxy_pass http://node;
      }
}

上面的設定檔在 least_time 後面額外添加了 headerinflight 參數,這代表了我們判斷最短時間的依據是回傳 response header 所需的時間, 也可以選用 last_byte 參數將判斷改成完整回傳 response 的時間,最後的 inflight 參數代表會把報錯的也計算到統計時間內。


Hash(商業版)

haship_hash 命令類似,不過 hash 能夠自己指定要進行雜湊計算的 key 值,不像是 ip_hash 只能夠只用客戶端的 IP 來做為 key 值, 所以這邊可以搭配自訂的 cookie 變數讓雜湊之後的結果為固定的一個值,也能做到像 ip_hash 那種固定轉換到某一台機器上的結果。

使用 hash 的設定檔會有以下內容

upstream node {
      hash $cookie_sessionid consistent;
      server 192.168.0.17:80;
      server 192.168.0.16:80;
}
server {
      listen 80 default_server;
      listen [::]:80 default_server;
      
      location / {
          proxy_pass http://node;
      }
}

上面的設定檔使用了 hash 方法, key 值為 $cookie_sessionid 變數,這樣當我們傳送請求的 cookie 內有 sessionid 這個 header 時就會自動 將 value 進行雜湊計算,最後搭配了 consistent 參數內部能夠切換到另一種雜湊算法 ketama,使用這個算法可以降低伺服器數量增加或減少時對效能的影響。


Random(商業版)

random 則是全部從 Server Group 挑選一台伺服器,還可以另外搭配 two 參數這樣就會變成全隨機挑選兩台伺服器,最後還需要指定一種分配方法例如 least_conn ,這樣的結果就會變成隨機挑選兩台然後再使用 least_conn 方法從這兩台中挑選出要轉發的一台伺服器。

使用 random 的設定檔會有以下內容

upstream node {
      random two least_conn;
      server 192.168.0.17:80;
      server 192.168.0.16:80;
}
server {
      listen 80 default_server;
      listen [::]:80 default_server;
      
      location / {
          proxy_pass http://node;
      }
}

Summary

今天學習了 Http Load Balancer 內提供的轉發方法,除了社群版提供的方法外還學習了商業版提供的方法, 下一篇文章會挑選幾個轉發方法進行測試,看看是不是真的會像說明那樣進行轉發。