- Linux集群之美
- 余洪春
- 2072字
- 2021-01-08 10:57:43
1.3.5 基于cookie的會(huì)話保持處理機(jī)制
這里用HAProxy來(lái)舉例說(shuō)明。
任何一個(gè)L7的HTTP負(fù)載均衡器都應(yīng)該具備一個(gè)功能:會(huì)話保持。會(huì)話保持是保證客戶端對(duì)動(dòng)態(tài)應(yīng)用程序正確請(qǐng)求的基本要求。
還是用那個(gè)最有說(shuō)服力的例子:客戶端A向服務(wù)端B請(qǐng)求將C商品加入它的賬戶購(gòu)物車,加入成功后,服務(wù)端B會(huì)在某個(gè)緩存區(qū)域中記錄下客戶端A和它的商品C,這個(gè)緩存的內(nèi)容就是Session上下文環(huán)境。而識(shí)別客戶端的方式一般是設(shè)置Session ID(如PHPSESSID、JSESSIONID),并將其作為cookie的內(nèi)容交給客戶端。客戶端A再次請(qǐng)求的時(shí)候(比如為購(gòu)物車中的商品下訂單),只要攜帶這個(gè)cookie,服務(wù)端B就可以從中獲取Session ID并找到屬于客戶端A的緩存內(nèi)容(商品C),也就可以繼續(xù)執(zhí)行下訂單部分的代碼。
假如這時(shí)使用負(fù)載均衡軟件對(duì)客戶端的請(qǐng)求進(jìn)行負(fù)載均衡,就必須要保證能將客戶端A的請(qǐng)求再次引導(dǎo)到服務(wù)端B,而不能引導(dǎo)到服務(wù)端X、服務(wù)端Y,因?yàn)閄、Y上并沒(méi)有緩存與客戶端A對(duì)應(yīng)的Session內(nèi)容,也就無(wú)法為客戶端A下訂單。
因此,反向代理軟件必須具備將客戶端和服務(wù)端“綁定”的功能,也就是所謂的提供會(huì)話保持,讓客戶端A后續(xù)的請(qǐng)求一定轉(zhuǎn)發(fā)到服務(wù)端B上。
在LB上配置好HAProxy后,HAProxy將接受用戶的所有請(qǐng)求。如果一個(gè)用戶請(qǐng)求不包含任何cookie,那么這個(gè)請(qǐng)求將被HAProxy轉(zhuǎn)發(fā)到一臺(tái)可用的Web服務(wù)器上,可能是WebA、WebB、WebC或WebD。然后HAProxy將把處理這個(gè)請(qǐng)求的Web服務(wù)器的cookie值插入請(qǐng)求響應(yīng)中,如SERVERID=A,若這個(gè)客戶端再次訪問(wèn)并在HTTP請(qǐng)求頭中帶有SERVERID=A,HAProxy將會(huì)把它的請(qǐng)求直接轉(zhuǎn)發(fā)給WebA處理。下面介紹實(shí)驗(yàn)的系統(tǒng)及開(kāi)源軟件的版本。
系統(tǒng)及開(kāi)源軟件版本:
·CentOS 7.6 x86_64
·HAProxy 1.7.9
·Nginx 1.12.2
·PHP 5.6.40
機(jī)器IP地址分配情況如下。
·HAProxy:192.168.100.22
·Nginx+PHP-1:192.168.100.23
·Nginx+PHP-2:1921.68.100.24
HAProxy代理兩臺(tái)Nginx機(jī)器,物理拓?fù)漭^簡(jiǎn)單,如圖1-5所示。

圖1-5 HAProxy代理Nginx物理拓?fù)鋱D
首先,源碼安裝HAProxy 1.7.9,由于CentOS 7.6系統(tǒng)自帶的HAProxy版本過(guò)低,這里想采用較高的開(kāi)源版本,所以以源碼方式進(jìn)行安裝:
cd /usr/local/src wget http://www.haproxy.org/download/1.7/src/haproxy-1.7.9.tar.gz tar xvf haproxy-1.7.9.tar.gz cd haproxy-1.7.9 make TARGET=linux2628 PREFIX=/usr/local/haproxy # TARGET指定編譯OS對(duì)應(yīng)的內(nèi)核版本,這里寫Linux2628即可 make install PREFIX=/usr/local/haproxy
為了實(shí)現(xiàn)基于cookie的會(huì)話保持,HAProxy配置文件中必須增加cookie的配置,如下所示:
# 需要轉(zhuǎn)發(fā)的IP及端口 balance roundrobin cookie SERVERID insert indirect nocache server web1 192.168.100.23:80 cookie server1 server web2 192.168.100.24:80 cookie server2
在這個(gè)示例配置中,cookie指令中指定的是insert命令,表示在將響應(yīng)報(bào)文交給客戶端之前,先插入一個(gè)屬性名為SERVERID的cookie,這個(gè)cookie在響應(yīng)報(bào)文的頭部獨(dú)占一個(gè)Set-Cookie字段(因?yàn)槭遣迦胄耤ookie),而SERVERID只是cookie名稱,它的值是由server指令中的cookie選項(xiàng)指定的,這里是server1或server2。
除了insert命令,cookie指令中還支持rewrite和prefix這兩種設(shè)置cookie的方式,不過(guò),對(duì)于這三種cookie的操作方式,只能三選一。
·insert:表示如果客戶端沒(méi)有cookie信息且有權(quán)限訪問(wèn)服務(wù)器時(shí),持久性cookie必須通過(guò)HAProxy穿插在服務(wù)器的響應(yīng)報(bào)文中。當(dāng)服務(wù)器收到相同名稱的cookie并且沒(méi)有“preserve(保存)”選項(xiàng)時(shí),將會(huì)移除之前已存的cookie信息。因此,insert可視作rewrite的升級(jí)版。cookie信息僅僅作為會(huì)話cookie且不會(huì)存到客戶端的磁盤上。默認(rèn)除非加了“indirect(間接)”選項(xiàng),否則服務(wù)器端會(huì)看到客戶端發(fā)送的cookie信息。由于緩存的影響,最好加上nocache或postonly選項(xiàng)。
·rewrite:表示cookie由服務(wù)器生成并且HAProxy會(huì)在其值中注入該服務(wù)器的標(biāo)識(shí)符;此關(guān)鍵字不能在HTTP隧道模式下工作。
·prefix:表示不依賴專用的cookie做持久性,而是依賴現(xiàn)成的;用在某些特殊的場(chǎng)景中,如客戶端不支持一個(gè)以上的cookie和應(yīng)用程序?qū)λ行枨髸r(shí)。每當(dāng)服務(wù)器建立一個(gè)名為<name>的cookie時(shí),它將以服務(wù)器的標(biāo)識(shí)符和分隔符作為前綴。來(lái)自客戶端的請(qǐng)求報(bào)文中的前綴將會(huì)被刪除以便服務(wù)器端能識(shí)別出它所發(fā)出的cookie,由于請(qǐng)求和響應(yīng)報(bào)文都被修改過(guò),所以此模式不能工作在隧道模式中,且不能與indirect共用,否則服務(wù)器端更新的cookie將不會(huì)被發(fā)到客戶端。
這里參考一下HAProxy官方文檔,它提供了cookie相關(guān)的配置說(shuō)明,如下所示。
HAProxy將在客戶端沒(méi)有cookie時(shí)(比如第一次請(qǐng)求),在響應(yīng)報(bào)文中插入一個(gè)cookie。
當(dāng)沒(méi)有使用關(guān)鍵詞preserve選項(xiàng)時(shí),如果后端服務(wù)器設(shè)置了一個(gè)與此處名稱相同的cookie,則首先刪除服務(wù)端設(shè)置的cookie。
該cookie只能作為會(huì)話保持使用,無(wú)法持久化到客戶端的磁盤上(因?yàn)镠AProxy設(shè)置的cookie沒(méi)有maxAge屬性,無(wú)法持久保存,只能保存在瀏覽器緩存中)。
默認(rèn)情況下,除非使用了indirect選項(xiàng),否則服務(wù)端可以看到客戶端請(qǐng)求時(shí)的所有cookie信息。
由于緩存的影響,建議加上nocache或postonly選項(xiàng)。如果使用nocache選項(xiàng),當(dāng)客戶端和HAProxy間存在緩存時(shí),使用此選項(xiàng)和insert搭配最好,以便確保如果一個(gè)cookie需要被插入時(shí),可被緩存的響應(yīng)會(huì)被標(biāo)記成不可緩存。這很重要,舉個(gè)例子:如果所有的持久cookie被添加到一個(gè)可緩存的主頁(yè)上,之后所有的客戶將從外部高速緩存讀取頁(yè)面并將共享相同的持久性cookie,這會(huì)造成服務(wù)器阻塞。
最后,我們利用后端test.php文件來(lái)區(qū)分客戶端連接的實(shí)際機(jī)器,test.php文件內(nèi)容如下:
<h1>response from webapp 192.168.100.23</h1> <?php session_start(); echo "Server IP: "."<font color=red>".$_SERVER['SERVER_ADDR']."</font>"."<br>"; echo "Server Name: "."<font color=red>".$_SERVER['SERVER_NAME']."</font>"."<br data-tomark-pass>"; echo "SESSIONNAME: "."<font color=red>".session_name()."</font>"."<br data-tomark-pass>"; echo "SESSIONID: "."<font color=red>".session_id()."</font>"."<br data-tomark-pass>"; ?>
另一臺(tái)機(jī)器相對(duì)應(yīng)的內(nèi)容改為:
<h1>response from webapp 192.168.100.24</h1>
接下來(lái)用如下地址訪問(wèn)HAProxy:
http://192.168.100.22/test.php
我們可以看一下訪問(wèn)http://192.168.100.22/test.php的結(jié)果顯示,如圖1-6所示。

圖1-6 test.php訪問(wèn)結(jié)果圖示
第一次訪問(wèn)時(shí)我們用Chrome瀏覽器的F12抓下HTTP的包,如圖1-7所示。

圖1-7 Chrome截圖結(jié)果圖示
再次訪問(wèn)時(shí),對(duì)比一下,Response Headers已經(jīng)沒(méi)有Set_Cookie了,這是什么原因呢?
具體原因?yàn)椋嚎蛻舳嗽诘谝淮问盏巾憫?yīng)后就會(huì)把cookie緩存下來(lái),以后每次http://192.168.100.22/test.php(根據(jù)域名進(jìn)行判斷)都會(huì)從緩存中取出該cookie放進(jìn)請(qǐng)求首部。這樣HAProxy一定會(huì)將其分配給Web1,除非Web1下線了。
這樣就實(shí)現(xiàn)了會(huì)話保持,保證被處理過(guò)的客戶端能被分配到同一個(gè)后端應(yīng)用服務(wù)器上。
參考文檔:
- Windows Server 2019 Cookbook
- Linux Mint Essentials
- 玩到極致 iPhone 4S完全攻略
- 新手易學(xué):系統(tǒng)安裝與重裝
- 嵌入式Linux應(yīng)用開(kāi)發(fā)菜鳥(niǎo)進(jìn)階
- Linux使用和管理指南:從云原生到可觀測(cè)性
- Joomla! 3 Template Essentials
- Advanced TypeScript Programming Projects
- OpenSolaris設(shè)備驅(qū)動(dòng)原理與開(kāi)發(fā)
- AWS SysOps Cookbook
- Windows 7使用詳解(修訂版)
- iOS 10 開(kāi)發(fā)指南
- OpenVZ Essentials
- Linux深度攻略
- 深入理解Android:卷III