這是1998年一個(gè)普通的上午。
一上班,老板就把張大胖叫進(jìn)了辦公室,一邊舒服地喝茶一邊發(fā)難:“大胖啊,我們公司開發(fā)的這個(gè)網(wǎng)站,現(xiàn)在怎么越來越慢了? ”
還好張大胖也注意到了這個(gè)問題,他早有準(zhǔn)備,一臉無奈地說: “唉,我昨天檢查了一下系統(tǒng),現(xiàn)在的訪問量已經(jīng)越來越大了,無論是CPU,還是硬盤、內(nèi)存都不堪重負(fù)了,高峰期的響應(yīng)速度越來越慢。”
頓了一下,他試探地問道:“老板,能不能買個(gè)好機(jī)器? 把現(xiàn)在的‘老破小’服務(wù)器給替換掉。我聽說IBM的服務(wù)器挺好的,性能強(qiáng)勁,要不來一臺(tái)?”
(碼農(nóng)翻身注:這叫垂直擴(kuò)展 Scale Up)
“好你個(gè)頭,你知道那機(jī)器得多貴嗎?! 我們小公司,用不起啊!” 摳門的老板立刻否決。
“這......” 大胖表示黔驢技窮了。
“你去和CTO Bill 商量下, 明天給我弄個(gè)方案出來。”
老板不管過程,只要結(jié)果。
1隱藏真實(shí)服務(wù)器
大胖悻悻地去找Bill。
他將老板的指示聲情并茂地做了傳達(dá)。
Bill笑了:“我最近也在思考這件事,想和你商量一下,看看能不能買幾臺(tái)便宜的服務(wù)器,把系統(tǒng)多部署幾份,橫向擴(kuò)展(Scale Out)一下。 ”
橫向擴(kuò)展? 張大胖心中尋思著,如果把系統(tǒng)部署到幾個(gè)服務(wù)器上,用戶的訪問請求就可以分散到各個(gè)服務(wù)器,那單臺(tái)服務(wù)器的壓力就小得多了。
“可是,” 張大胖問道 ,“機(jī)器多了,每個(gè)機(jī)器一個(gè)IP, 用戶可能就迷糊了,到底訪問哪一個(gè)?”
“肯定不能把這些服務(wù)器暴露出去,從客戶角度看來,最好是只有一個(gè)服務(wù)器。” Bill 說道。
張大胖眼前一亮, 突然有了主意:“有了!我們有個(gè)中間層啊,對,就是DNS,我們可以設(shè)置一下,讓我們網(wǎng)站的域名映射到多個(gè)服務(wù)器的IP,用戶面對的是我們系統(tǒng)的域名,然后我們可以采用一種輪詢的方式, 用戶1的機(jī)器做域名解析的時(shí)候,DNS返回IP1, 用戶2的機(jī)器做域名解析的時(shí)候,DNS返回IP2...... 這樣不就可以實(shí)現(xiàn)各個(gè)機(jī)器的負(fù)載相對均衡了嗎?”
Bill 思考片刻,發(fā)現(xiàn)了漏洞:“這樣做有個(gè)很要命的問題,由于DNS這個(gè)分層的系統(tǒng)中有緩存,用戶端的機(jī)器也有緩存,如果某個(gè)機(jī)器出故障,域名解析仍然會(huì)返回那個(gè)出問題機(jī)器的IP,那所有訪問該機(jī)器的用戶都會(huì)出問題, 即使我們把這個(gè)機(jī)器的IP從DNS中刪除也不行, 這就麻煩了。”
張大胖確實(shí)是沒想到這個(gè)緩存帶來的問題, 他撓撓頭:“那就不好辦了。”
2偷天換日
“要不我們自己開發(fā)一個(gè)軟件實(shí)現(xiàn)負(fù)載均衡怎么樣?” Bill另辟蹊徑。
為了展示自己的想法, 他在白板上畫了一張圖, “看到中間那個(gè)藍(lán)色服務(wù)器沒有,我們可以把它稱為Load Balancer (簡稱LB), 用戶的請求都發(fā)給他,然后它再發(fā)給各個(gè)服務(wù)器。”
張大胖仔細(xì)審視這個(gè)圖。
Load Balancer 簡稱LB, 有兩個(gè)IP,一個(gè)對外(115.39.19.22),一個(gè)對內(nèi)(192.168.0.100)。用戶看到的是那個(gè)對外的IP。 后面的真正提供服務(wù)的服務(wù)器有三個(gè),稱為RS1, RS2,RS3, 他們的網(wǎng)關(guān)都指向LB。
“但是怎么轉(zhuǎn)發(fā)請求呢?嗯, 用戶的請求到底是什么東西?” 張大胖迷糊了。
“你把計(jì)算機(jī)網(wǎng)絡(luò)都忘了吧? 就是用戶發(fā)過來的數(shù)據(jù)包嘛! 你看這個(gè)層層封裝的數(shù)據(jù)包,用戶發(fā)了一個(gè)HTTP的請求,想要訪問我們網(wǎng)站的首頁,這個(gè)HTTP請求被放到一個(gè)TCP報(bào)文中,再被放到一個(gè)IP數(shù)據(jù)報(bào)中, 最終的目的地就是我們的Load Balancer(115.39.19.22)。”
(注: 客戶發(fā)給LB的數(shù)據(jù)包, 沒有畫出數(shù)據(jù)鏈路層的幀)
“但是這個(gè)數(shù)據(jù)包一看就是發(fā)給Load Balancer的, 怎么發(fā)給后面的服務(wù)器?”
Bill 說: “可以偷天換日,比如Load Balancer想把這個(gè)數(shù)據(jù)包發(fā)給RS1(192.168.0.10), 就可以做點(diǎn)手腳,把這個(gè)數(shù)據(jù)包改成這樣, 然后這個(gè)IP數(shù)據(jù)包就可以轉(zhuǎn)發(fā)給RS1去處理了。”
(LB動(dòng)了手腳,把目的地IP和端口改為RS1的)
“RS1處理完了,要返回首頁的HTML,還要把HTTP報(bào)文層層封裝:” 張大胖明白怎么回事了:
(RS1處理完了,要發(fā)送結(jié)果給客戶端)
“由于LB是網(wǎng)關(guān),它還會(huì)收到這個(gè)數(shù)據(jù)包,它就可以再次施展手段,把源地址和源端口都替換為自己的,然后發(fā)給客戶就可以了。”
(LB再次動(dòng)手腳,把源地址和端口改成自己的, 讓客戶端毫無察覺)
張大胖總結(jié)了一下數(shù)據(jù)的流向:
客戶端-->Load Balancer-->RS-->Load Balancer--> 客戶端
他興奮地說:“這招瞞天過海真是妙啊,客戶端根本就感受不到后面有好幾臺(tái)服務(wù)器在工作,它一直以為只有Load Balancer在干活。”
Bill此刻在思考Load Balancer 怎么樣才能選取后面的各個(gè)真實(shí)的服務(wù)器, 可以有很多種策略,他在白板上寫到:
輪詢: 這個(gè)最簡單,就是一個(gè)挨一個(gè)輪換。
加權(quán)輪詢: 為了應(yīng)對某些服務(wù)器性能好,可以讓他們的權(quán)重高一點(diǎn),被選中的幾率大一點(diǎn)。
最少連接: 哪個(gè)服務(wù)器處理的連接少,就發(fā)給誰。
加權(quán)最少連接:在最少連接的基礎(chǔ)上,也加上權(quán)重
......
還有些其他的算法和策略,以后慢慢想。
3四層還是七層?
張大胖卻想到了另外一個(gè)問題: 對于用戶的一個(gè)請求來說,可能會(huì)被分成多個(gè)數(shù)據(jù)包來發(fā)送,如果這些數(shù)據(jù)包被我們的Load Balancer發(fā)到了不同的機(jī)器上,那就完全亂套了啊! 他把自己的想法告訴了Bill。
Bill說:“這個(gè)問題很好啊,我們的Load Balancer必須得維護(hù)一個(gè)表,這個(gè)表需要記錄下客戶端的數(shù)據(jù)包被我們轉(zhuǎn)發(fā)到了哪個(gè)真實(shí)的服務(wù)器上, 這樣當(dāng)下一個(gè)數(shù)據(jù)包到來時(shí),我們就可以把它轉(zhuǎn)發(fā)到同一個(gè)服務(wù)器上去。”
“看來這個(gè)負(fù)載均衡軟件需要是面向連接的,也就是OSI網(wǎng)絡(luò)體系的第4層, 可以稱為四層負(fù)載均衡”Bill做了一個(gè)總結(jié)。
“既然有四層負(fù)載均衡,那是不是也可以搞個(gè)七層的負(fù)載均衡啊?” 張大胖突發(fā)奇想。
“那是肯定的,如果我們的Load Balancer把HTTP層的報(bào)文數(shù)據(jù)取出來,根據(jù)其中的URL,瀏覽器,語言等信息,把請求分發(fā)到后面真實(shí)的服務(wù)器去,那就是七層的負(fù)載均衡了。不過我們現(xiàn)階段先實(shí)現(xiàn)一個(gè)四層的吧,七層的以后再說。”
Bill 吩咐張大胖組織人力把這個(gè)負(fù)載均衡軟件給開發(fā)出來。
張大胖不敢怠慢,由于涉及到協(xié)議的細(xì)節(jié)問題,張大胖還買了幾本書:《TCP/IP詳解》 卷一,卷二,卷三, 帶著人快速復(fù)習(xí)了C語言, 然后開始瘋狂開發(fā)。
4責(zé)任分離
三個(gè)月后,Load Balancer的第一版開發(fā)出來了,這是運(yùn)行在Linux上的一個(gè)軟件, 公司試用了一下,感覺還真是不錯(cuò),僅僅用幾臺(tái)便宜的服務(wù)器就可以實(shí)現(xiàn)負(fù)載均衡了。
老板看到?jīng)]花多少錢就解決了問題,非常滿意,給張大胖所在的開發(fā)組發(fā)了1000塊錢獎(jiǎng)金,組織大家出去搓了一頓。
張大胖他們看到老板很摳門,雖略有不滿,但是想到通過這個(gè)軟件的開發(fā),學(xué)到了很多底層的知識(shí),尤其是TCP協(xié)議,也就忍了。
可是好景不長,張大胖發(fā)現(xiàn)這個(gè)Load Balancer存在這瓶頸:所有的流量都要通過它,它要修改客戶發(fā)來的數(shù)據(jù)包, 還要修改發(fā)給客戶的數(shù)據(jù)包。
網(wǎng)絡(luò)訪問還有個(gè)極大的特點(diǎn),那就是請求報(bào)文較短而響應(yīng)報(bào)文往往包含大量的數(shù)據(jù)。這是很容易理解的,一個(gè)HTTP GET請求短得可憐,可是返回的HTML卻是極長 -- 這就進(jìn)一步加劇了Load Balancer修改數(shù)據(jù)包的工作。
張大胖趕緊去找Bill ,Bill說:“這確實(shí)是個(gè)問題,我們把請求和響應(yīng)分開處理吧,讓Load Balancer只處理請求,讓各個(gè)服務(wù)器把響應(yīng)直接發(fā)給客戶端,這樣瓶頸不就消除了嗎?”
“怎么分開處理?”
“首先讓所有的服務(wù)器都有同一個(gè)IP, 我們把他稱為VIP吧(如圖中115.39.19.22)。”
張大胖通過第一版Load Balancer的開發(fā),積累了豐富的經(jīng)驗(yàn)。
他問道:“你這是把每個(gè)實(shí)際服務(wù)器的loopback都綁定了那個(gè)VIP, 不過有問題啊,這么多服務(wù)器都有同樣的IP , 當(dāng)IP數(shù)據(jù)包來的時(shí)候,到底應(yīng)該由哪個(gè)服務(wù)器來處理?”
“注意,IP數(shù)據(jù)包其實(shí)是通過數(shù)據(jù)鏈路層發(fā)過來的,你看看這個(gè)圖。”
張大胖看到了客戶端的HTTP報(bào)文再次被封裝儲(chǔ)層TCP報(bào)文,端口號(hào)是80, 然后IP數(shù)據(jù)報(bào)中的目的地是115.39.19.22(VIP)。
圖中的問號(hào)是目的地的MAC地址, 該怎么得到呢?
對, 是使用ARP協(xié)議,把一個(gè)IP地址(115.39.19.22)給廣播出去,然后具有此IP機(jī)器就會(huì)回復(fù)自己的MAC地址。 但是現(xiàn)在有好幾臺(tái)機(jī)器都有同一個(gè)IP(115.39.19.22), 怎么辦?
Bill 說道:“我們只讓Load Balancer 響應(yīng)這個(gè)VIP地址(115.39.19.22)的ARP請求,對于RS1,RS2,RS3, 抑制住對這個(gè)VIP地址的ARP響應(yīng),不就可以唯一地確定Load Balancer了? ”
原來如此!張大胖恍然大悟。
既然Load Balancer得到了這個(gè)IP數(shù)據(jù)包, 它就可以用某個(gè)策略從RS1, RS2,RS3中選取一個(gè)服務(wù)器,例如RS1(192.168.0.10),把IP數(shù)據(jù)報(bào)原封不動(dòng), 封裝成數(shù)據(jù)鏈路層的包(目的地是RS1的MAC地址),直接轉(zhuǎn)發(fā)就可以了。
RS1(192.168.0.10)這個(gè)服務(wù)器收到了數(shù)據(jù)包,拆開一看,目的地IP是115.39.19.22,是自己的IP, 那就可以處理了。
處理完了以后,RS1可以直接響應(yīng)發(fā)回給客戶端,完全不用再通過Load Balancer。因?yàn)樽约旱牡刂肪褪?15.39.19.22。
對于客戶端來說,它看到的還是那個(gè)唯一的地址115.39.19.22, 并不知道后臺(tái)發(fā)生了什么事情。
Bill補(bǔ)充到:“由于Load Balancer 根本不會(huì)修改IP數(shù)據(jù)報(bào),其中的TCP的端口號(hào)自然也不會(huì)修改,這就要求RS1, RS2,RS3上的端口號(hào)必須得和Load Balancer一致才行。”
像之前一樣,張大胖總結(jié)了一下數(shù)據(jù)的流向:
客戶端-->Load Balancer--> RS --> 客戶端
Bill 說道:“怎么樣? 這個(gè)辦法還可以吧?”
張大胖又想了想,這種方式似乎沒有漏洞,并且效率很高,Load Balancer只負(fù)責(zé)把用戶請求發(fā)給特定的服務(wù)器就萬事大吉了, 剩下的事由具體的服務(wù)器來處理,和它沒有關(guān)系了。
他高興地說:“不錯(cuò),我著手帶人去實(shí)現(xiàn)了。”
后記:本文所描述的,其實(shí)就是著名開源軟件LVS的原理,上面講的兩種負(fù)載均衡的方式,就是LVS的NAT和DR。
LVS是章文嵩博士在1998年5月成立的自由軟件項(xiàng)目,現(xiàn)在已經(jīng)是Linux內(nèi)核的一部分。想想那時(shí)候我還在不亦樂乎地折騰個(gè)人網(wǎng)頁,學(xué)會(huì)安裝和使用Linux 沒多久 , 服務(wù)器端開發(fā)也僅限于ASP,像LVS這種負(fù)載均衡的概念壓根就沒有聽說過。
編程語言可以學(xué),差距也能彌補(bǔ),但是這種境界和眼光的差距,簡直就是巨大的鴻溝,難以跨越啊!
(完)
"Linux閱碼場"是專業(yè)的Linux及系統(tǒng)軟件技術(shù)交流社區(qū),Linux系統(tǒng)人才培養(yǎng)基地,企業(yè)和Linux人才的連接樞紐。
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
9237瀏覽量
85664 -
DNS
+關(guān)注
關(guān)注
0文章
219瀏覽量
19876 -
負(fù)載均衡
+關(guān)注
關(guān)注
0文章
112瀏覽量
12373
原文標(biāo)題:負(fù)載均衡的原理
文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論