通過Cookie Insertion實現(xiàn)Nginx會話保持

Nginx負(fù)載均衡的幾種策略

使用開源版本的Nginx可以輕松實現(xiàn)7層(HTTP)或4層(TCP)的負(fù)載均衡详炬。

當(dāng)做為7層負(fù)載時趴腋,最常用的有以下幾種策略:

  • 輪詢 round-robin — requests to the application servers are distributed in a round-robin fashion 依次把客戶端的請求分發(fā)到不同的后端服務(wù)器上
  • 最少連接 least-connected — next request is assigned to the server with the least number of active connections 請求會被轉(zhuǎn)發(fā)到連接數(shù)最少的服務(wù)器上
  • IP哈希 ip-hash — a hash-function is used to determine what server should be selected for the next request (based on the client’s IP address) 同一客戶端(IP)的連續(xù)的請求都會被分發(fā)到固定的一臺后端服務(wù)器上

前兩種方案(輪詢和最少連接)同一客戶端的請求會被隨機(jī)分配后不同的后端服務(wù)器上,如果后端是傳統(tǒng)的有狀態(tài)的WEB應(yīng)用佩番,則需要在后端WEB容器上配置Session共享,非常麻煩。

后一種方案(IP哈希)可以識別請求端的IP瓦糟,固定將其分配到某一臺后端服務(wù)器上,輕松解決了會話保持的問題赴蝇。但I(xiàn)P哈希存在一個比較嚴(yán)重缺陷菩浙,即:客戶端必須能夠直連Nginx服務(wù)器,他們之間不能再插入其它層級,否則Nginx就識別不到客戶端的IP了劲蜻。

那除了IP HASH外陆淀,還有沒有其它方式能夠進(jìn)行會話保持呢?

Cookie Insertion

以下是官網(wǎng)的關(guān)于Cookie Insertion的介紹:

Cookie Insertion:NGINX Plus adds a session cookie to the first response from the upstream group to a given client, identifying which server generated the response (in an encoded fashion). Subsequent requests from the client include the cookie value and NGINX Plus uses it to route the request to the same upstream server:

Cookie植入:

  1. 客戶端第一次訪問時先嬉,負(fù)載均衡服務(wù)在返回請求中植入cookie(在HTTP/HTTPS響應(yīng)報文中插入)
  2. 下次客戶端攜帶此cookie訪問轧苫,負(fù)載均衡服務(wù)會將請求定向轉(zhuǎn)發(fā)給之前記錄到的后端服務(wù)器上。

Cookie植入原理上就是劫持HTTP請求疫蔓,偽造cookie含懊,它可以在Nginx無法獲取客戶端IP時,也依然能夠完成會話保持的功能衅胀,只要客戶端支持Cookie即可岔乔。

購買并使用Nginx Plus

要使用Cookie Insertion,最簡便的方式是使用商業(yè)版本的Nginx Plus滚躯,默認(rèn)支持雏门。

以下是官網(wǎng)關(guān)于會話保持的介紹:
https://www.nginx.com/products/session-persistence/

Cookie Insertion的配置非常簡單:

upstream backend {
    server webserver1;
    server webserver2;
    sticky cookie srv_id expires=1h domain=.example.com path=/;
}

于是順道了解了一下Nginx Plus的來龍去脈:

  • 2002年,來自俄羅斯的Igor Sysoev使用C語言開發(fā)了NGINX掸掏;
  • 2004年茁影,NGINX開放源碼,基于BSD開源許可阅束。
  • 2006年 - 2016年呼胚,NIGNX Rlease版本歷經(jīng)0.5, 0.6, 0.7, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 1.9, 1.10, 1.11, 當(dāng)前最新版本為1.11.3;
  • 2011年息裸,Sysoev成立了NGINX公司蝇更,NGINX PLUS是其第一款產(chǎn)品,也是NGINX的商業(yè)版本呼盆;
  • 2013年 - 2016年年扩,自NGINX Plus Initial Release (R1)版本發(fā)布以來,NGINX商業(yè)版本已更新至NGINX Plus Release 9 (R9)访圃;

NGINX Plus is the all-in-one application delivery platform for the modern web.
All-In-One的NGINX PLUS對比開源版本重點(diǎn)增加了若干企業(yè)特性厨幻,包括更完善的七層、四層負(fù)載均衡腿时,會話保持况脆,健康檢查,實時監(jiān)控和管理等批糟。

可看了一下最便宜的BASIC版本也要2500刀每年格了,淚奔,果斷PASS徽鼎。
https://www.nginx.com/products/buy-nginx-plus/

使用第三方模塊nginx-sticky-module

流傳最廣的是一個名為 nginx-sticky-module 的第3方的模塊 盛末,不過已經(jīng)有多年沒有維護(hù)弹惦。

GoogleCode頁面(需扶墻): https://code.google.com/archive/p/nginx-sticky-module/downloads

下載 nginx-sticky-module-1.1.tar.gz ,看看能否配合較新的 nginx-1.12.1 使用悄但。

Nginx下載地址: https://nginx.org/en/download.html

選擇Stable version中的nginx-1.12.1

簡單編譯一下試試:

./configure --prefix=/nginx/nginx-1.12.1 --add-module=/nginx/src/nginx-sticky-module-1.1  
make && make install

果然報錯:

/nginx/src/nginx-sticky-module-1.1/ngx_http_sticky_module.c: In function ‘ngx_http_get_sticky_peer’:
/nginx/src/nginx-sticky-module-1.1/ngx_http_sticky_module.c:333: error: assignment makes pointer from integer without a cast
make[1]: *** [objs/addon/nginx-sticky-module-1.1/ngx_http_sticky_module.o] Error 1
make[1]: Leaving directory `/nginx/src/nginx-1.12.1'
make: *** [build] Error 2

代碼太老舊棠隐,沒有細(xì)查的必要了,棄用檐嚣。

使用第三方模塊nginx-sticky-module-ng

另外還有一個比較新的模塊 nginx-sticky-module-ng 助泽,源碼托管在BitBucket上:
https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng/

在Downloads/Tags下,找到1.2.6的源碼并下載净嘀,或者直接下載Master分支上最新的代碼报咳。

在編譯之前侠讯,首先來動手修復(fù)一個BUG挖藏。。厢漩。
找到ngx_http_sticky_misc.c膜眠,添加以下兩個include:

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

第三方的東西湊和著用吧。溜嗜。宵膨。

編譯一下試試:

./configure --prefix=/nginx/nginx-1.12.1 --add-module=/nginx/src/nginx-sticky-module-ng
make && make install

編譯很順利,配置一下試試吧:
配置上非常簡單炸宵,只需要在upstream{}中加入sticky即可辟躏。

upstream {
  sticky;
}

Sticky的詳細(xì)配置說明:
sticky [name=route] [domain=.foo.bar] [path=/] [expires=1h]
[hash=index|md5|sha1] [no_fallback] [secure] [httponly];

  • name: the name of the cookies used to track the persistant upstream srv; default: route
  • domain: the domain in which the cookie will be valid default: nothing. Let the browser handle this.
  • path: the path in which the cookie will be valid default: /
  • expires: the validity duration of the cookie default: nothing. It's a session cookie. restriction: must be a duration greater than one second
  • hash: the hash mechanism to encode upstream server. It cant' be used with hmac. default: md5
  • md5|sha1: well known hash
  • index: it's not hashed, an in-memory index is used instead, it's quicker and the overhead is shorter Warning: the matching against upstream servers list is inconsistent. So, at reload, if upstreams servers has changed, index values are not guaranted to correspond to the same server as before! USE IT WITH CAUTION and only if you need to!
  • hmac: the HMAC hash mechanism to encode upstream server It's like the hash mechanism but it uses hmac_key to secure the hashing. It can't be used with hash. md5|sha1: well known hash default: none. see hash.
  • hmac_key: the key to use with hmac. It's mandatory when hmac is set default: nothing.
  • no_fallback: when this flag is set, nginx will return a 502 (Bad Gateway or Proxy Error) if a request comes with a cookie and the corresponding backend is unavailable.
  • secure enable secure cookies; transferred only via https
  • httponly enable cookies not to be leaked via js

下面給出一個完整的配置:

worker_processes  4;

events {
    worker_connections 1024;
}

http {
    upstream proxy_admin {
        #ip_hash;
        sticky;
        server 192.168.1.61:19022 weight=10 max_fails=3 fail_timeout=20s;
        server 192.168.1.62:19022 weight=10 max_fails=3 fail_timeout=20s;
    }

    server {
        listen       29022;
        server_name  proxy_admin;
        location / {
            root   html;
            proxy_pass   http://proxy_admin;
            proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
            proxy_redirect off;
            proxy_ignore_client_abort on;
            proxy_set_header Host $host:$server_port;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header REMOTE-HOST $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_connect_timeout 60;
            proxy_send_timeout 60;
            proxy_read_timeout 60;
            proxy_buffer_size 4k;
            proxy_buffers 4 32k;
            proxy_busy_buffers_size 64k;
            proxy_temp_file_write_size 64k;
            client_body_buffer_size 128k;
        }
    }
}

測試,用瀏覽器訪問一下試試:
http://IP:29022/mobagent-admin/
如果在控制臺中的Cookie中看到一個名為route的鍵土全,就說明基本上成功了捎琐。
然后多請求幾次,看看后端服務(wù)的日志裹匙,最終確認(rèn)一下瑞凑,是不是只指向了同一臺服務(wù)器。

注意事項

最后概页,請注意籽御,因為nginx-sticky-module-ng的可靠性未經(jīng)長時間驗證,請勿直接用于生產(chǎn)系統(tǒng)惰匙。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末技掏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子项鬼,更是在濱河造成了極大的恐慌哑梳,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秃臣,死亡現(xiàn)場離奇詭異涧衙,居然都是意外死亡哪工,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門弧哎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雁比,“玉大人,你說我怎么就攤上這事撤嫩≠松樱” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵序攘,是天一觀的道長茴她。 經(jīng)常有香客問我,道長程奠,這世上最難降的妖魔是什么丈牢? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮瞄沙,結(jié)果婚禮上己沛,老公的妹妹穿的比我還像新娘。我一直安慰自己距境,他們只是感情好申尼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著垫桂,像睡著了一般师幕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诬滩,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天霹粥,我揣著相機(jī)與錄音,去河邊找鬼碱呼。 笑死蒙挑,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的愚臀。 我是一名探鬼主播忆蚀,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼姑裂!你這毒婦竟也來了馋袜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤舶斧,失蹤者是張志新(化名)和其女友劉穎欣鳖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茴厉,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡泽台,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年什荣,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怀酷。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡稻爬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜕依,到底是詐尸還是另有隱情桅锄,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布样眠,位于F島的核電站友瘤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏檐束。R本人自食惡果不足惜辫秧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望厢塘。 院中可真熱鬧茶没,春花似錦、人聲如沸晚碾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽格嘁。三九已至,卻和暖如春廊移,著一層夾襖步出監(jiān)牢的瞬間糕簿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工狡孔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留懂诗,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓苗膝,卻偏偏與公主長得像殃恒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子辱揭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容