問題初現(xiàn)
「滴~~~」,釘釘突然響起了很多客服轉(zhuǎn)發(fā)來的用戶投訴信息,說是網(wǎng)絡(luò)連接不上了,經(jīng)過排查發(fā)現(xiàn)是其中一臺機(jī)器(RS2)掛了
但是 LVS 依然持續(xù)地把流量打到這臺機(jī)器上,持續(xù)造成線上問題,小章首先把這臺機(jī)器從 LVS 上摘除,先保證線上正常,然后為了避免之后出現(xiàn)類似問題,急忙找了 CEO 老梁來商討方案。
應(yīng)用層健康檢查:HTTP 檢測
老梁一眼看出了問題所在:「我們需要開發(fā)一個(gè)健康檢查服務(wù),部署在 LVS 上,這個(gè)服務(wù)可以定時(shí)檢查其后的 RS 是否可用,如果不可用則將 RS 摘除,這樣就可以保障線上服務(wù)正常了」
「妙啊,通過軟件及時(shí)探測,摘除不可用的機(jī)器,避免了人工發(fā)現(xiàn)不及時(shí)的問題,那么該怎么做這個(gè)健康檢查呢,需要滿足什么條件呢」聽說要開發(fā)這樣的軟件,小章頓時(shí)來了興致。
「小章啊,仔細(xì)想想看,我們的服務(wù)在發(fā)布過程中其實(shí)也是有健康檢查的,要保證一個(gè)工程可用,至少保證它是可訪問的以及它用到的中間件,DAO 是正常的,所以它的健康代碼如下
@Service(protocol={"rest"}) publicclassHealthCheckServiceImplimplementsHealthCheckService{ @Resource privateTestDAOTestDAO; @Resource privateRebateClientrebateClient; @Override publicStringgetHealthStatus(){ List
testDOS= TestDAO.getResult(123); Assert.isTrue(testDOS!=null,"rebateMemberDOSnull"); //此處省略redis檢測 //此處省略其它檢測 return"health"; } }
如以上代碼所示,我們在工程里寫了健康檢查 HealthCheckService 類,暴露了一個(gè) rest 服務(wù),這樣的話在部署的時(shí)候在服務(wù)部署腳本里首先訪問一下此服務(wù)的 getHealthStatus 方法,如果返回的值為「health」,則說明此服務(wù)的 dubbo 服務(wù),DAO,redis 等正常,說明此服務(wù)是沒有問題的,如果返回的值不為 health,則說明此服務(wù)有問題,不能上線,這就是我們所說的健康檢查,通過訪問服務(wù)暴露的方法,來檢測此服務(wù)是否可用。
所以我們要開發(fā)的檢測服務(wù)也與此類似,只要定時(shí)訪問此服務(wù)暴露的接口,看下此接口返回的值與我們期待的值是否一致即可,一致說明此服務(wù)正常,否則,說明此服務(wù)異常,將其剔除,當(dāng)然了一次連接不通就判斷為不可用可能有些問題,我們可以提供一個(gè)重試次數(shù),比如 3 次,如果 3 次健康檢測都失敗,則認(rèn)定此服務(wù)不可用!配置的偽代碼如下:
real_server192.168.1.22080{
HTTP_GET{
url{
path/healthCheck
status_code200
}
connect_timeout3
nb_get_retry3//置超時(shí)重試次數(shù)
}
}
「妙啊,此法甚好!只要訪問健康檢查服務(wù)就可以很方便地查看此服務(wù)是否正常了,但是有個(gè)問題:如果這個(gè)健康檢測方法寫的檢測邏輯很多,而 LVS 定時(shí)發(fā)檢測請求比較頻繁的話可能會有一定的性能問題,是否有更輕量級的檢測方法呢」小章說道
「考慮得很周到!一般健康檢測確實(shí)邏輯比較重,所以只在部署的的時(shí)候檢測一次就夠了,在生產(chǎn)上我們可以采用更輕量的檢測方式:TCP連接檢測」
TCP連接檢測
TCP 連接檢測原理很簡單,我們知道要建立一個(gè) TCP 連接,首先必須由 TCP 客戶端發(fā)起 connect 請求,三次握手成功后才算建立起一個(gè) TCP 鏈接,然后才能正常收發(fā)數(shù)據(jù)
所以我們只要調(diào)用 connect 方法看它是否成功即可,成功即說明連接建立成功,說明服務(wù)是可用的,如果失敗說明此服務(wù)有問題,直接摘除即可,當(dāng)然了與 HTTP 檢測一樣,也要有超時(shí)機(jī)制,偽代碼如下
tcp連接檢測
TCP_CHECK{
connect_port80//指定端口
connect_timeout6//設(shè)置響應(yīng)超時(shí)時(shí)間
nb_get_retry3//設(shè)置超時(shí)重試次數(shù)
delay_before_retry3//設(shè)置超時(shí)重試間隔時(shí)間
}
小章按著老梁的思路把這兩種健康檢測思路給實(shí)現(xiàn)了,并且給這個(gè)服務(wù)取了個(gè)霸氣的名字:keepalived,老梁很滿意,不過他又發(fā)現(xiàn)了新的問題。。。
單點(diǎn)故障---高可用解決之道
「小章,健康檢查做得很好,而且提供了兩種檢查方式,很全面,不過你這個(gè)架構(gòu)還有個(gè)很致命的問題,不知你有沒發(fā)現(xiàn),那就是目前只有一臺 LVS 在工作,如果這臺 LVS 掛了,那我們業(yè)務(wù)就跌零了, 你還需要讓 keepalived 支持 LVS 的高可用」
小章恍然大悟,「那該咋辦呢」
「高可用的通用解決方案很簡單,冗余+故障自動發(fā)現(xiàn)轉(zhuǎn)移,我們可以按照這個(gè)思路來設(shè)計(jì) LVS 高可用,具體方案如下:
我們可以為 LVS 準(zhǔn)備幾臺備機(jī),如果發(fā)現(xiàn) LVS 掛了,就讓備機(jī)頂上去,這樣不就實(shí)現(xiàn)了高可用了嗎」不愧是 CTO,一語中的
小章看了一眼架構(gòu)圖,提出了三個(gè)問題
-
如果主機(jī)(以下簡稱 master)宕機(jī),備機(jī)(以下簡稱 backup)頂上,那 IP 地址不是變了嗎,此時(shí)客戶端該怎么連接
-
幾臺機(jī)器首次啟動時(shí),誰為 master,誰為 backup
-
master 宕機(jī)后,backup 是如何感知到的,多臺 backup 又是如何競選出主機(jī)的,這個(gè)和問題 2 有點(diǎn)類似
「這幾個(gè)問題提的很好,正是實(shí)現(xiàn)高可用的關(guān)鍵,可以看出小伙子還是有經(jīng)過深入思考的」老梁高興地說,「這些問題不難化解,我們一一來看看」
問題一:backup 成為 master 后,IP 地址變了怎么辦?
答:IP 地址不能變,對外必須表現(xiàn)為一個(gè) IP,我們通常稱為「虛擬(virtual) IP」,通常簡稱為 VIP
如果 master(即圖中的 L1)工作,則此 VIP 在 master 上可用,若 master 宕機(jī),如果 backup(比如 L2)競選 master 成功,則 VIP 在 L2 上生效,同時(shí)新的 master 需要發(fā)送一個(gè)攜帶有本機(jī)的 MAC 地址和 VIP 地址信息的 ARP 報(bào)文,你會發(fā)現(xiàn) VIP 從老的 master 轉(zhuǎn)移到競選 master 成功的 backup 上了,我們把這種現(xiàn)象稱為 IP 漂移,這里有兩個(gè)問題需要澄清
-
一個(gè)主機(jī)如何才能有兩個(gè) IP
-
為什么 VIP 在某臺競選 master 成功的 backup 上生效后要發(fā)一個(gè)攜帶有本機(jī)的 MAC 地址和 VIP 地址信息的 ARP 報(bào)文
先看第一個(gè)問題,主機(jī)如何才能擁有兩個(gè) IP ,畢竟一臺機(jī)器成為主機(jī)后,除了本身機(jī)器被分配的 IP(115.205.4.210),VIP 也漂移到它身上了,此時(shí)它擁有兩個(gè) IP
我們知道計(jì)算機(jī)要上網(wǎng),首先要把網(wǎng)線插入網(wǎng)卡,一個(gè)網(wǎng)卡其實(shí)就對應(yīng)著一個(gè) IP,所以一臺主機(jī)配兩個(gè)網(wǎng)卡就可以綁定兩個(gè) IP,一般 LVS 都會配置雙網(wǎng)卡,一來每個(gè)網(wǎng)卡帶寬都是有限的,雙網(wǎng)卡相當(dāng)于提升了一倍的帶寬,二來兩個(gè)網(wǎng)卡也起到了熱備的作用,如果一個(gè)網(wǎng)卡壞了,另外一個(gè)可以頂上。
但有人說了,我就只有一個(gè)網(wǎng)卡,也想配置多個(gè) IP,是否可以?
答案是可以的,網(wǎng)卡一般分兩種,一種是物理網(wǎng)卡,一種是虛擬網(wǎng)卡
-
物理網(wǎng)卡
:可以插網(wǎng)線的網(wǎng)卡,如果有多個(gè)網(wǎng)卡,我們一般將其命名為 eth0,eth1。。。,如果一個(gè)網(wǎng)卡對應(yīng)多個(gè) IP,以 eth0 為例,一般將其命名為 eth0,eth0:0,eth0:1。。。eth0:x,比如一臺機(jī)器只有一個(gè)網(wǎng)卡,但其對應(yīng)兩個(gè) IP 192.168.1.2, 192.168.1.3,那么其綁定的網(wǎng)卡名稱分別為 eth0,eth0:0 -
虛擬網(wǎng)卡
:虛擬網(wǎng)卡通常被稱為 loopback,一般命名為 lo,是一個(gè)特殊的網(wǎng)絡(luò)接口,主要用于本機(jī)中各個(gè)應(yīng)用之間的網(wǎng)絡(luò)交互(哪怕網(wǎng)線拔了,本機(jī)各個(gè)應(yīng)用之間通過 lo 也是能通信的),需要注意的是虛擬網(wǎng)卡和物理網(wǎng)卡一樣,也可以綁定任意 IP 地址,如果在虛擬網(wǎng)卡配置了任何的 IP 地址,只要有物理網(wǎng)卡,就能到收到并處理目的 IP 為虛擬網(wǎng)卡上 IP 的數(shù)據(jù)包,lo 默認(rèn)綁定了 127.0.0.1 這個(gè)本地 IP ,如果要綁定其他的 IP,對應(yīng)的網(wǎng)卡命名一般為 lo:0,lo:1。。。
所以假設(shè)一臺機(jī)器只有一個(gè)網(wǎng)卡,一般內(nèi)網(wǎng)給它默認(rèn)分配的 IP 綁定在 eth0 上,那么我們就可以把虛擬 IP 綁定在 eth0:0 上,這樣的話外界就能正常訪問此虛擬 IP 了,如果 master 掛掉了,keepalived 會讓此 master 的 eth0:0 端口失效,同時(shí)讓新 master 的 eth0:0 綁定虛擬 IP,這樣就避免了對外暴露兩個(gè)虛擬 IP。
再來看第二位問題,虛擬 IP 在某臺機(jī)器生效后,為啥要發(fā)一個(gè) ARP 請求呢,這個(gè)問題其實(shí)在之前的文章中提到過,這里為了照顧其他沒看過之前文章的讀者,再簡單提一下,其實(shí)上面的架構(gòu)圖我們作了一定程度的簡化,更詳細(xì)的應(yīng)該如下圖所示
如圖示,三臺 LVS 機(jī)器組成一個(gè)同一網(wǎng)段的以太網(wǎng)我們知道,以太網(wǎng)是以 mac 地址來尋址的,我們知道現(xiàn)在對外暴露的是虛擬 IP,那么當(dāng)帶有虛擬 IP 的包到達(dá)路由器時(shí),它該怎么找到對應(yīng)的機(jī)器呢?
一開始它啥也不知道,所以它在網(wǎng)址發(fā)了一個(gè) ARP 廣播包,相當(dāng)于大吼一聲:IP 地址為 115.205.4.213 的機(jī)器是誰啊,由于這個(gè)虛擬 IP 在 L1 上,所以只有 L1 響應(yīng)了,L1 會把帶有自己 mac 地址的響應(yīng)包發(fā)回給路由器,路由器收到后會把 IP 地址與 L1 mac 地址的關(guān)系記在本地,然后在包的頭部裝上 L1 的 mac 地址發(fā)給交換機(jī),交換機(jī)就能識別到應(yīng)該發(fā)給 L1,下次當(dāng)客戶端再次發(fā)數(shù)據(jù)包到路由器時(shí),路由器會首先在本地緩存(ARP 緩存)中查到 IP 對應(yīng)的 mac(即 L1 的mac),命中后將包上的 mac 地址替換成 L1 的 mac 轉(zhuǎn)發(fā)出去,至此相信你應(yīng)該明白為啥虛擬 IP 生效后要發(fā) ARP 報(bào)文了,就是為了更新由器上的 ARP 緩存,將虛擬 IP 對應(yīng)的 mac 地址更新為競選 master 成功的 backup 上的 mac,這樣下次路由器就能正確將新 master 的 mac 附在數(shù)據(jù)包上,就能正確地轉(zhuǎn)發(fā)到機(jī)器上了,否則,數(shù)據(jù)包會轉(zhuǎn)發(fā)到老的 master 上,引起災(zāi)難性的后果!
問題二:幾臺機(jī)器首次啟動后,誰為 master,誰為 backup
這個(gè)問題其實(shí)很簡單,誰的能力強(qiáng),誰就優(yōu)先成為 master,我們可以給各個(gè)機(jī)器設(shè)置不同的值為 0~255 的權(quán)重,權(quán)重越大,代表此機(jī)器越有可能成為 master(如果權(quán)重一樣,則比較它們的 IP,IP 大的權(quán)重高),這里分幾種情況
-
每個(gè)機(jī)器啟動后都處于 Initialize 狀態(tài),若某臺機(jī)器接口(eth0)Up 之后,如果其權(quán)重為 255 且此時(shí)還沒有 master 則其成為 master 并且讓虛擬 IP 綁定在 eth0:0 端口上,如果此時(shí)已有 master 呢,分兩種模式:搶占和非搶占模式,如果處于非搶占模式下,則它轉(zhuǎn)為 backup 狀態(tài),否則它會重新競爭成為 master,此時(shí)一般能競爭成功,因?yàn)樗幱谧罡邫?quán)重(一般只有一臺機(jī)器處于最高權(quán)限)
-
如果某臺機(jī)器權(quán)重不為 255,則經(jīng)過一段時(shí)間后如果此時(shí)還沒有 master ,那么它會競爭 master,如果此時(shí)有了 master,也和情況 1 一樣,分搶占和非搶占模式,為啥要經(jīng)過一段時(shí)間才競爭 master 呢,其實(shí)主要是為了優(yōu)先讓權(quán)重為 255 的機(jī)器成為 master
問題三: master 宕機(jī)后,backup 是如何感知到的,多臺 backup 又是如何競選出主機(jī)的
當(dāng)機(jī)器成為 master 后,它會定時(shí)發(fā)送廣播給其他的 backup,讓其他 backup 知道它還存活著,如果在指定時(shí)間內(nèi)(一般我們稱此時(shí)間為 Master_Down_Interval)backup 沒有收到 master 的廣播包,那么 backup 互相之間會發(fā)廣播包通過比較權(quán)重競爭 master,某臺 backup 競選 master 成功后同樣會讓虛擬 IP 綁定在 eth0:0 端口上,并且發(fā)送 ARP 包讓路由器等更新自己的 ARP 緩存,其他競選失敗的則轉(zhuǎn)為 backup 狀態(tài)
至此相信大家已經(jīng)明白了 keepalived 的工作機(jī)制,所有上面說的這些工作只要配置一下 keepalived 的配置文件并啟動后即可實(shí)現(xiàn)。
另外 keepalived 實(shí)現(xiàn)的高可用機(jī)制不光可以用在 LVS 上,也可以用在 MySQL 等高可用上,所以你內(nèi)部工程連 MySQL 的地址一般是虛擬 IP?,F(xiàn)在我相信你能看懂如下 LVS 的高可用工作圖了
注:不管是 master 還是 backup 都能對背后的 RS 作健康檢查哦
總結(jié)
相信大家看完本文對 keepalived 的工作原理應(yīng)該是了然于胸了,它的主要工作模式無非就兩塊:「健康檢查」和「高可用」,健康檢查我們只介紹了常見的兩種,其實(shí)它還支持通過運(yùn)行腳本來作健康檢測,只是不太常用而已,另外 keepalived 的高可用可以說是大放異彩,除了用在 LVS 的高可用,還用在 Nginx ,MySQL 的高可用上,原理其實(shí)無非就是利用心跳檢測+競爭 master + IP 漂移來實(shí)現(xiàn),完整的 keepalived.conf 配置文件大家有興趣可以看文末的參考鏈接,相信經(jīng)過上面的原理講解再去看此文件不是問題
另外不知大家是否注意到了,master 雖然可以定時(shí)向 backup 發(fā)送心跳,但如果此心跳鏈路壞了 backup 就會誤認(rèn)為 master 已經(jīng)不可用了,從而去申請成為 master,這樣就會造成兩個(gè) master 的出現(xiàn),也就是我們常說的腦裂,怎么解決?可以同時(shí)用兩條心跳線路,這樣一條心跳檢測線路壞了,另一條還是好的,依然能傳送心跳消息。當(dāng)然除了心跳鏈路壞了還有可能會有其他情況也會導(dǎo)致腦裂的發(fā)生,我們還是要做好多種預(yù)案,必要時(shí)人工及時(shí)介入,(關(guān)于腦裂的更多信息可以看文末的參考鏈接)
-
負(fù)載
+關(guān)注
關(guān)注
2文章
576瀏覽量
34450 -
IP
+關(guān)注
關(guān)注
5文章
1716瀏覽量
149865 -
LVS
+關(guān)注
關(guān)注
1文章
36瀏覽量
9964
原文標(biāo)題:負(fù)載均衡之備胎轉(zhuǎn)正
文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論