摘要:因?yàn)槲覀冋J(rèn)為正常情況下用戶的不會(huì)在短時(shí)間內(nèi)發(fā)生變化,所以當(dāng)我們選擇使用策略進(jìn)行負(fù)載均衡時(shí),意味著期望同一個(gè)用戶能夠一直訪問到同一臺(tái)服務(wù)器上,就像下圖這樣。但是,我們還需要明白一個(gè)事實(shí)嚴(yán)格來說保持本質(zhì)上是破壞了做負(fù)載均衡的初衷。
本文長(zhǎng)度為3056字,預(yù)計(jì)讀完需1.1MB流量,建議閱讀8分鐘。
這篇是《分布式關(guān)注點(diǎn)系列》中「負(fù)載均衡」相關(guān)的內(nèi)容最后一發(fā)了,后續(xù)也會(huì)繼續(xù)講「高可用」相關(guān)的其它主題,主要是限流、降級(jí)、熔斷之類的吧,具體還沒定。文末先附上之前發(fā)過的高可用相關(guān)文章,供你再溫故一下。
下面這個(gè)場(chǎng)景不知是否在你面前出現(xiàn)過。
開發(fā)Z哥對(duì)運(yùn)維Y弟喊:“Y弟,現(xiàn)在系統(tǒng)好卡,剛上了一波活動(dòng),趕緊幫我加幾臺(tái)機(jī)器上去頂一下?!?p>Y弟回復(fù)說:“沒問題,分分鐘搞定”。然后就發(fā)現(xiàn)數(shù)據(jù)庫(kù)的壓力迅速上升,DBA就吼了:“Z哥,你丫的搞什么呢?數(shù)據(jù)庫(kù)要被你弄垮了”。
然后客服那邊接框也爆炸了,越來越多的用戶說剛登陸后沒多久,操作著就退出了,接著登陸,又退出了,到底還做不做生意了。
這些問題背后都是由于一個(gè)「Session丟失」問題導(dǎo)致的。
一、什么是Session丟失相信Session對(duì)大部分Coder來說應(yīng)該都知道。它是為了將同一個(gè)用戶的多次訪問在系統(tǒng)中被識(shí)別為“同一個(gè)用戶”而產(chǎn)生的概念。除此之外,還可以基于它來減少重復(fù)往DB或者遠(yuǎn)程服務(wù)處獲取與該用戶相關(guān)的信息,以起到提升性能的作用。
在我們做了負(fù)載均衡的場(chǎng)景中,如果選擇的負(fù)載策略是hash策略,那么會(huì)使得Session產(chǎn)生一個(gè)副作用,這個(gè)副作用就如上面舉的案例那樣,用戶一旦由于某種原因從原先訪問服務(wù)器A變成訪問服務(wù)器B,就會(huì)出現(xiàn)“登陸狀態(tài)丟失”、“緩存穿透”等問題。
為什么hash策略會(huì)出現(xiàn)這個(gè)問題呢?首先有必要先了解一下hash是如何進(jìn)行的。hash策略就是下圖這樣的一個(gè)散列函數(shù)。在函數(shù)不變的情況下,A永遠(yuǎn)對(duì)應(yīng)01,B對(duì)應(yīng)04,C對(duì)應(yīng)08。
▲圖片來源于網(wǎng)絡(luò),版權(quán)歸原作者所有
以nginx中的ip_hash策略來舉個(gè)例子。因?yàn)槲覀冋J(rèn)為正常情況下用戶的ip不會(huì)在短時(shí)間內(nèi)發(fā)生變化,所以當(dāng)我們選擇使用ip_hash策略進(jìn)行負(fù)載均衡時(shí),意味著期望同一個(gè)用戶能夠一直訪問到同一臺(tái)服務(wù)器上,就像下圖這樣。
▲圖中的hash函數(shù)是最簡(jiǎn)單的隨意舉例
如此一來,我們只需要在這一臺(tái)服務(wù)器上將這個(gè)用戶相關(guān)的信息緩存在進(jìn)程內(nèi),就能起到非常高性價(jià)比的提升性能的效果。
這時(shí),客戶端與服務(wù)端之間的相當(dāng)于建立了一個(gè)信任,相互認(rèn)識(shí)。這個(gè)信任就是「Session」。
但是,當(dāng)我們加了一臺(tái)服務(wù)器之后,事情就發(fā)生變化了。
▲圖中的hash函數(shù)是最簡(jiǎn)單的隨意舉例
這個(gè)時(shí)候我們?cè)鹊念A(yù)期就被破壞了。因?yàn)橛脩襞c序號(hào)0節(jié)點(diǎn)的鏈接變成了與序號(hào)3的鏈接,所以產(chǎn)生了前面提到的「Session丟失」問題。與此同時(shí),在序號(hào)0節(jié)點(diǎn)上做的進(jìn)程內(nèi)緩存都無效了,而在序號(hào)3節(jié)點(diǎn)上又沒有用戶相關(guān)的任何緩存,導(dǎo)致大量數(shù)據(jù)需要從下游的DB或者遠(yuǎn)程服務(wù)處獲取。你要知道,一旦涉及到網(wǎng)絡(luò)通信,性能必然明顯下降,I/O、序列化都是耗時(shí)的工作。更重要的是,一旦同時(shí)有大量用戶產(chǎn)生這個(gè)情況,由于后端的DB和遠(yuǎn)程服務(wù)瞬時(shí)無法承載激增的高密度請(qǐng)求,可能會(huì)導(dǎo)致它掛起。這還沒完,如果當(dāng)前程序沒有一些故障隔離或者降級(jí)策略,還會(huì)進(jìn)一步產(chǎn)生蝴蝶效應(yīng),導(dǎo)致整個(gè)大系統(tǒng)響應(yīng)緩慢??芍^“一顆老鼠屎壞了一鍋粥”。
二、nginx是如何來解決這個(gè)問題的既然以nginx舉例,還是從nginx開始聊。通過在nginx中引入nginx-sticky-module模塊可以來解決這個(gè)問題。解決的整個(gè)過程如下。
▲圖片來源于網(wǎng)絡(luò),版本歸原作者所有
可以看到,當(dāng)client第一次進(jìn)入到nginx匹配節(jié)點(diǎn)的時(shí)候,在給它分配一個(gè)節(jié)點(diǎn)的同時(shí),會(huì)將這個(gè)節(jié)點(diǎn)的唯一標(biāo)識(shí)進(jìn)行md5后寫入到cookie中一并返回,如果下次再發(fā)起請(qǐng)求的時(shí)候發(fā)現(xiàn)帶有這個(gè)cookie值,就直接轉(zhuǎn)發(fā)到該值所對(duì)應(yīng)的節(jié)點(diǎn)上去。這個(gè)機(jī)制被專業(yè)的稱之為「Session保持」。
雖然可以利用cookie來解決這個(gè)問題,但是cookie也有一個(gè)潛在的問題,如果客戶端未開啟cookie功能,這個(gè)機(jī)制就失效了。不過好在目前主流瀏覽器都是默認(rèn)打開cookie的。
題外話:nginx是2004年發(fā)布的,在nginx-sticky-module出現(xiàn)之前的7年間也是nginx相比競(jìng)品HAProxy最大的一個(gè)短板,因?yàn)镠AProxy支持Session保持。三、Session保持的其它方案
除了cookie之外,還有2種方式也可以最終達(dá)到類似的效果。分別被稱為「Session復(fù)制」、「Session共享」。
01 Session復(fù)制這是最簡(jiǎn)單粗暴的方式。根據(jù)第一節(jié)的案例來看,導(dǎo)致問題的原因是節(jié)點(diǎn)3沒有用戶的Session。那么很容易想到,在節(jié)點(diǎn)3運(yùn)行之前把Session相關(guān)的Cache數(shù)據(jù)復(fù)制過去唄。并且在多個(gè)節(jié)點(diǎn)之間持續(xù)保證數(shù)據(jù)的同步,也就是說,每一臺(tái)節(jié)點(diǎn)上都存在每個(gè)用戶的Session數(shù)據(jù)。
實(shí)現(xiàn)的方案有很多,特別是不同的宿主程序都或多或少提供了一些切入點(diǎn),甚至是拿來即用的方案,如Tomcat的Delta Manager和Backup Manager、Tomcat和IIS的Filter機(jī)制等等,這里就不展開了。
此類方案的特點(diǎn)是
優(yōu)點(diǎn):天然高可用,一部分節(jié)點(diǎn)宕機(jī)沒事。因?yàn)槊恳粋€(gè)節(jié)點(diǎn)上存放著所有已連接用戶的會(huì)話信息。
缺點(diǎn):因?yàn)槊颗_(tái)計(jì)算機(jī)的內(nèi)存是有上限的,僅適用于會(huì)話相關(guān)的數(shù)據(jù)大小較小的場(chǎng)景。并且,由于多個(gè)節(jié)點(diǎn)之間需要同步數(shù)據(jù),需要額外解決數(shù)據(jù)一致性問題。與此同時(shí),隨著節(jié)點(diǎn)越多,損耗越大(延遲、帶寬等),有廣播風(fēng)暴風(fēng)險(xiǎn)。
02 Session共享我們還可以通過將session信息存放到全局共享的存儲(chǔ)介質(zhì)中來達(dá)到一樣的效果,如數(shù)據(jù)庫(kù)、遠(yuǎn)程緩存等,這是一種中心化思想的解決方案。
此類方案的特點(diǎn)是
優(yōu)點(diǎn):不管節(jié)點(diǎn)怎么增加和減少,100%不會(huì)產(chǎn)生會(huì)話丟失。
缺點(diǎn):每次讀寫請(qǐng)求都需要增加額外共享儲(chǔ)存調(diào)用,增加了網(wǎng)絡(luò)I/O、序列化等操作,性能明顯下降。另外,用作共享的存儲(chǔ)介質(zhì)除了增加了額外的維護(hù)成本外,還需要解決單點(diǎn)問題,以免產(chǎn)生系統(tǒng)性風(fēng)險(xiǎn)。
同之前「Session保持」方案一起對(duì)比下各自的優(yōu)缺點(diǎn)和適用場(chǎng)景。
分別用一句話概括一下這3個(gè)方案:
Session 保持。原來在哪還是去哪。
Session 復(fù)制。不管在哪都有一樣的數(shù)據(jù)。
Session 共享。所有節(jié)點(diǎn)共用一份數(shù)據(jù)。
越大型的系統(tǒng),最終都會(huì)往「Session共享」這個(gè)方案上走,因?yàn)橹灰賹?duì)這個(gè)共享存儲(chǔ)做橫向擴(kuò)展,理論上就可以支撐無窮大的用戶了。如Redis、一系列的NOSQL以及NEWSQL等。就像下面這樣,集「規(guī)模大」、「高可用」、「效果好」于一身。
四、結(jié)語(yǔ)現(xiàn)在你應(yīng)該清楚了Session丟失問題,也知道了如何去應(yīng)對(duì)他。但是,我們還需要明白一個(gè)事實(shí):嚴(yán)格來說「Session保持」本質(zhì)上是破壞了做「負(fù)載均衡」的初衷。舉個(gè)極端點(diǎn)的場(chǎng)景:一共有10個(gè)會(huì)話連在了節(jié)點(diǎn)A上,并且都是活動(dòng)中狀態(tài)。那么這個(gè)時(shí)候哪怕增加一個(gè)節(jié)點(diǎn)B上線,只要沒有新的會(huì)話進(jìn)來,節(jié)點(diǎn)B上的活動(dòng)連接數(shù)永遠(yuǎn)是0,并沒有起到分擔(dān)壓力的作用。
但是,在系統(tǒng)的起步時(shí)期,其實(shí)用這樣簡(jiǎn)單的方案也是極好的。
相關(guān)文章:
分布式系統(tǒng)關(guān)注點(diǎn)——初識(shí)「高可用」
分布式系統(tǒng)關(guān)注點(diǎn)——僅需這一篇,吃透「負(fù)載均衡」妥妥的
分布式系統(tǒng)關(guān)注點(diǎn)——如何去實(shí)施「負(fù)載均衡」?
? 關(guān)于作者:張帆(Zachary)。堅(jiān)持用心打磨每一篇高質(zhì)量原創(chuàng)。本文首發(fā)于公眾號(hào):「跨界架構(gòu)師」(ID:Zachary_ZF)。
微信公眾號(hào)(首發(fā)):跨界架構(gòu)師。<-- 點(diǎn)擊后閱讀熱門文章
定期發(fā)表原創(chuàng)內(nèi)容:架構(gòu)設(shè)計(jì)丨分布式系統(tǒng)丨產(chǎn)品丨運(yùn)營(yíng)丨一些深度思考。
掃碼加入小圈子 ↓
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/40168.html
摘要:在一個(gè)成熟的系統(tǒng)中,能夠運(yùn)用到緩存的地方其實(shí)并不是一處。那么在以終端用戶為起點(diǎn),系統(tǒng)所用的數(shù)據(jù)庫(kù)為終點(diǎn)的這條道路上可以作為緩存設(shè)立點(diǎn)的位置大致有以下這些。緩存也有一系列的副作用需要考慮。 如果這是第二次看到我的文章,歡迎文末掃碼訂閱我個(gè)人的公眾號(hào)(跨界架構(gòu)師)喲~ 本文長(zhǎng)度為3578字,建議閱讀10分鐘。堅(jiān)持原創(chuàng),每一篇都是用心之作~ 此前的「伸縮性」章節(jié)結(jié)束了,此文是「高性能」章...
摘要:首當(dāng)其沖的就是先寫還是緩存。先寫還是緩存一個(gè)程序可以沒有緩存,但是一定要有數(shù)據(jù)庫(kù)。為了便于記憶,你可以和分布式系統(tǒng)的定理同時(shí)記憶,叫緩存的模式。否則引入分布式緩存的作用就小了很多。就是設(shè)置緩存定時(shí)過期或者定時(shí)往下游的分布式緩存拉取最新數(shù)據(jù)。 如果第二次看到我的文章,歡迎文末掃碼訂閱我個(gè)人的公眾號(hào)(跨界架構(gòu)師)喲~ 本文長(zhǎng)度為4209字,建議閱讀12分鐘。堅(jiān)持原創(chuàng),每一篇都是用心之作...
摘要:為什么以前個(gè)人團(tuán)隊(duì)的工作,現(xiàn)在你一個(gè)人操作就做了,你覺得工資給你翻三倍過分嗎年,第九個(gè)需要布局的技術(shù)物聯(lián)網(wǎng)將推進(jìn)了服務(wù)器端,而不是桎梏與瀏覽器。 2010年的你,如果能學(xué)會(huì)Android開發(fā),現(xiàn)在的你,薪資不會(huì)低于年薪50萬(wàn)…… 2015年的你,如果能熟練使用react,現(xiàn)在的你,薪資不會(huì)低于月薪30K…… 看到這兩個(gè)數(shù)據(jù),也許有人會(huì)反駁:技術(shù)剛出來,沒人敢用,而且隨便一門技術(shù),用上三...
摘要:負(fù)載均衡器的作用是將請(qǐng)求的連接路由到最空閑的可用服務(wù)器上。負(fù)載均衡有五個(gè)常見目的可擴(kuò)展性。靈活的負(fù)載均衡方案能夠大幅提高服務(wù)的可用性。連接池和長(zhǎng)連接可能會(huì)阻礙負(fù)載均衡器分發(fā)連接請(qǐng)求。 負(fù)載均衡的基本思路很簡(jiǎn)單: 在一個(gè)服務(wù)器集群中盡可能地的平均負(fù)載量。 基于這個(gè)思路,我們通常的做法是在服務(wù)器前端設(shè)置一個(gè)負(fù)載均衡器。負(fù)載均衡器的作用是將請(qǐng)求的連接路由到最空閑的可用服務(wù)器上。如圖 1,顯示...
閱讀 1013·2023-04-25 14:41
閱讀 2464·2021-09-28 09:35
閱讀 3633·2019-08-30 15:53
閱讀 1950·2019-08-29 15:26
閱讀 1075·2019-08-28 17:59
閱讀 4340·2019-08-26 13:45
閱讀 2852·2019-08-26 13:33
閱讀 1654·2019-08-26 11:46