首頁 > 軟體

nginx sticky實現基於cookie負載均衡範例詳解

2022-12-21 14:01:36

前言

sticky 是一個nginx的第三方模組 它不在nginx發行版中 需要額外編譯這個模組的, 它的思想就是不依靠後端生成cookie , 而是sticky在nginx這裡生成cookie ,然後下發到使用者端, 使用者端收到cookie後 以後的請求帶著這個cookie 就會通過這個cookie 進行hash 被一直定位到後端的某一臺伺服器了

優點:

  • 它比純 ip hash 負載有個優點就是 純 ip hash 像區域網內的存取ip 存取會導致ip傾斜
  • 它比 hash $cookie_jsessionid的優點就是 它不依賴後端 不用後端生成 session 從而減少後端的 資源

思考

想想為什麼要用這個 sticky 來把使用者儘量一直定位到一臺伺服器呢? 在多臺後臺伺服器的環境下,我們為了確保一個客戶只和一臺伺服器通訊,我們勢必使用長連線。使用什麼方式來實現這種連線呢,常見的有使用nginx自帶的ip_hash來做,我想這絕對不是一個好的辦法,如果前端是CDN,或者說一個區域網的客戶同時存取伺服器,導致出現伺服器分配不均衡,以及不能保證每次存取都粘滯在同一臺伺服器。

如果基於cookie會是一種什麼情形,想想看, 每臺電腦都會有不同的cookie,在保持長連線的同時還保證了伺服器的壓力均衡,nginx sticky值得推薦。

如果瀏覽器不支援cookie,那麼sticky不生效,畢竟整個模組是給予cookie實現的.

1.cookie_jsessionid 負載均衡

在說sticky 之前先來看看 nginx 通過 cookie_jessionid 的負載均衡方式

1.1 後端準備

@Autowired
lateinit var env: Environment
@GetMapping("/server")
fun server(request:HttpServletRequest):String {
  //獲取當前服務的埠
  val port = env.getProperty("local.server.port")
  println("now port: $port")
  //呼叫了request.getSession(true) 則會沒有session的時候建立session
  val session = request.getSession(true)
  val name = session.getAttribute("name")
  println("name: $name")
  if (name == null){
    session.setAttribute("name","johnny")
  }
  return "success"
}

1.2 hash $cookie_jsessionid;設定

在upstream 裡面設定 hash 的方式 使用 cookie_jsessionid 去做hash

#user  nobody;
worker_processes  1;
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    #gzip  on;
    upstream backend {
        # 指定hash 方式是 cookie_jessionid nginx自帶的方式
        hash $cookie_jsessionid;
        server 172.16.225.1:8081;
			  server 172.16.225.1:8080;
    }
    server {
        listen       80;
        server_name  localhost;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
            # 指定負載到後端upstream
	    			proxy_pass http://backend;  
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

可以看到 伺服器下發了 cookie JSESSIONID 並且多次請求這個 都不會改變 因為nginx 根據 JSESSIONID 它進行hash 每次都負載到同一臺後端伺服器, 因為這個後端伺服器已經存在了 這個session 所以不會再次建立

可以看到 多次請求 都打到這個 8081 的後端服務了

2.nginx sticky 負載均衡

2.1 下載 sticky

Bitbucket

bitbucket.org/nginx-goodi…

2.2 重新編譯升級nginx

1)下載完成,放入伺服器解壓,記住解壓的位置,後面要用

2)進入到nginx的安裝檔案

3)設定nginx

tar -xvf nginx-goodies-nginx-sticky-module-ng-c78b7dd79d0d.tar.gz
mv nginx-goodies-nginx-sticky-module-ng-c78b7dd79d0d nginx-sticky
# 新增sticky 模組
./configure 
--prefix=/usr/local/nginx 
--add-module=/opt/nginx-sticky

make 編譯的時候有可能會報錯

找到sticky剛剛的解壓目錄,進入修改檔案 vim ngx_http_sticky_misc.c ,加入下面的標頭檔案

#include <openssl/sha.h> 
#include <openssl/md5.h>

再次make , 當然後面如果還報錯的話,openssl檢查是否安裝

apt-get install -y openssl 

2.3 upstream 設定 sticky

設定好後重啟nginx

  upstream backend {
        #hash $cookie_jsessionid;
        sticky; #指定使用 sticky 進行負載均衡
        server 172.16.225.1:8081;
				server 172.16.225.1:8080;
 }

2.4 修改後端不再建立session

此時後端不會建立session 也不會下發cookie jsessionid 了

@Autowired
lateinit var env: Environment
@GetMapping("/server")
fun server(request:HttpServletRequest):String {
    val port = env.getProperty("local.server.port")
    println("now port: $port")
    return "success"
}

2.5 再次 多次請求

可以看到stick 幫我們下發了 route 這個cookie , 並且這個不會變 預設關閉瀏覽器就會失效

可以看到請求還是隻會落在一臺伺服器上

3.sticky 其他用法

sticky [name=route] [domain=.foo.bar] [path=/] [expires=1h] [hash=index|md5|sha1] [no_fallback];

name: 可以為任何的string字元,預設是route

domain:哪些域名下可以使用這個cookie

path:哪些路徑對啟用sticky,例如path/test,那麼只有test這個目錄才會使用sticky做負載均衡

expires:cookie過期時間,預設瀏覽器關閉就過期,也就是對談方式。

no_fallbackup:如果設定了這個,cookie對應的伺服器宕機了,那麼將會返回502(bad gateway 或者 proxy error),建議不啟用

總結

本篇主要介紹了 nginx sticky 負載均衡,它不需要後端去生成session 下發jsessionid 而是nginx的sticky模組幫我們去下發一個 route 的 cookie , nginx 使用這個cookie 進行hash 負載, 從而實現了 客戶每次存取都粘滯在同一臺伺服器

以上就是nginx sticky實現基於cookie負載均衡範例詳解的詳細內容,更多關於nginx sticky cookie負載均衡的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com