本文并不試圖闡明所有JGroups協(xié)議,只針對(duì)部分工程中用到的協(xié)議做通俗易懂的闡述。關(guān)于完整的JGroups協(xié)議請(qǐng)參見(jiàn):
http://www.jgroups.org/manual4/index.html#protlist
發(fā)現(xiàn)協(xié)議(PING、MPING)
PING\MPING發(fā)現(xiàn)協(xié)議用于發(fā)現(xiàn)是否有其他節(jié)點(diǎn)加入指定名稱(chēng)的通道。一般來(lái)講,PING協(xié)議運(yùn)行在UDP之上,而MPING運(yùn)行在TCP之上,二者機(jī)制類(lèi)似。
PING\MPING協(xié)議用于動(dòng)態(tài)節(jié)點(diǎn)發(fā)現(xiàn),每個(gè)節(jié)點(diǎn)對(duì)PING消息的反饋消息包括協(xié)調(diào)者的地址和自己的地址,PING消息發(fā)送后等待指定時(shí)間(timeout屬性)或指定數(shù)量的節(jié)點(diǎn)(num_initial_members屬性)回復(fù)后,根據(jù)反饋消息確定協(xié)調(diào)者并發(fā)送JOIN消息。如果沒(méi)有收到任何反饋,會(huì)認(rèn)為自己是集群中第一個(gè)節(jié)點(diǎn)為協(xié)調(diào)者。
錯(cuò)誤檢測(cè)協(xié)議(FD_SOCK、FD_ALL、VERIFY_SUSPECT)
錯(cuò)誤探測(cè)協(xié)議用來(lái)發(fā)現(xiàn)集群中發(fā)生錯(cuò)誤的節(jié)點(diǎn),當(dāng)某一個(gè)節(jié)點(diǎn)發(fā)生錯(cuò)誤被探測(cè)到時(shí),會(huì)發(fā)送SUSPECT消息到所有節(jié)點(diǎn)。注意,SUSPECT只是通知其他節(jié)點(diǎn),某個(gè)節(jié)點(diǎn)當(dāng)前狀態(tài)時(shí)可疑的。SUSPECT消息僅由coordinator節(jié)點(diǎn)接收(GMS協(xié)議處理),其他節(jié)點(diǎn)忽略該消息。
FD_SOCK
FD_SOCK協(xié)議基于群組成員創(chuàng)建的TCP Socket完成錯(cuò)誤檢測(cè),集群中的任何一個(gè)節(jié)點(diǎn)都連接到它相鄰的下一節(jié)點(diǎn)(如A->B->C->A),由此形成了一個(gè)套接字環(huán)。
當(dāng)集群節(jié)點(diǎn)數(shù)量超過(guò)1個(gè)時(shí),JGroups將啟動(dòng)pinger線程。pinger線程連接其右側(cè)的鄰居,并等待socket關(guān)閉(通過(guò)read堵塞接口)。當(dāng)read接口發(fā)生IOException時(shí),認(rèn)定其鄰居為SUSPECT狀態(tài)。
該協(xié)議實(shí)現(xiàn)簡(jiǎn)單,并且不會(huì)帶來(lái)額外的流量開(kāi)銷(xiāo)。但當(dāng)服務(wù)器掛起或路由器崩潰時(shí),并不會(huì)檢測(cè)到socket關(guān)閉,檢測(cè)失效(準(zhǔn)確描述應(yīng)該是:在TCP的keepalive檢測(cè)超時(shí)后檢測(cè)到)。
FD_ALL
FD_ALL協(xié)議基于簡(jiǎn)單的心跳協(xié)議,每個(gè)節(jié)點(diǎn)周期性的發(fā)送組播心跳。同時(shí)每個(gè)節(jié)點(diǎn)維護(hù)了一份完整的集群節(jié)點(diǎn)列表(除了自身節(jié)點(diǎn)),當(dāng)收到來(lái)自節(jié)點(diǎn)P的心跳數(shù)據(jù)時(shí),更新節(jié)點(diǎn)P的時(shí)間到當(dāng)前時(shí)間。節(jié)點(diǎn)每個(gè)一定周期檢測(cè)哪些過(guò)期的節(jié)點(diǎn)(時(shí)間長(zhǎng)期未更新的節(jié)點(diǎn)),并發(fā)其SUSPECT流程。
VERIFY_SUSPECT
VERIFY_SUSPCET協(xié)議通過(guò)ping的方式再次確認(rèn)可疑節(jié)點(diǎn)是否已終止。如已終止,則向上發(fā)送SUSPECT通知,將該節(jié)點(diǎn)移除;否則,直接丟棄SUSPECT消息。
默認(rèn)情況下,向SUSPECT節(jié)點(diǎn)發(fā)送一個(gè)確認(rèn)心跳消息,等待2秒鐘。如果SUSPECT節(jié)點(diǎn)響應(yīng)則丟棄SUSPECT消息,如無(wú)響應(yīng)則認(rèn)定節(jié)點(diǎn)丟失,向上發(fā)送SUSPECT通知。
合并協(xié)議(MERGE3)
如果網(wǎng)絡(luò)異常發(fā)生,集群可能被分割成多個(gè)區(qū)域而形成多個(gè)集群(多個(gè)協(xié)調(diào)者)。合并協(xié)議負(fù)責(zé)將分割成的多個(gè)區(qū)域重新合并成一個(gè)集群(通過(guò)多個(gè)協(xié)調(diào)者之間的溝通)。
在MERGE3協(xié)議中,所有節(jié)點(diǎn)周期性的發(fā)送INFO消息,消息內(nèi)容包括:地址信息(UUID),邏輯名,物理地址和ViewId。
ViewId用于查看集群成員內(nèi)部間是否存在意見(jiàn)分歧:每個(gè)coordinator周期性的查看目前收到的INFO消息,并檢查是否存在任何的不一致。如果存在不一致,將地址(UUID)最小的一個(gè)當(dāng)作merge leader,這確保同一時(shí)刻只有一個(gè)merge leader。隨后,merge leader收集到完整的信息,并發(fā)送MERGE請(qǐng)求給GMS,由GMS完成真正的MERGE動(dòng)作。
群組成員關(guān)系協(xié)議(pbcast.GMS)
GMS即群組成員關(guān)系協(xié)議,該協(xié)議時(shí)JGroups協(xié)議棧中的重要協(xié)議,它維護(hù)者一個(gè)活著節(jié)點(diǎn)的列表。GMS負(fù)責(zé)群組成員加入和離開(kāi)群組的請(qǐng)求,同時(shí)它也處理錯(cuò)誤探測(cè)協(xié)議發(fā)送的SUSPECT協(xié)議。
消息穩(wěn)定性協(xié)議(pbcast.STABLE)
為了處理可能的重發(fā)請(qǐng)求,節(jié)點(diǎn)需保存收到的message,直到集群中所有的節(jié)點(diǎn)都收到了該消息。消息穩(wěn)定性(message stability)是指:對(duì)于給定的消息M,M可以被集群中的每個(gè)節(jié)點(diǎn)收到。
但是如果我們永遠(yuǎn)保存接收到的消息,則我們會(huì)面臨內(nèi)存溢出的問(wèn)題。分布式垃圾回收協(xié)議負(fù)責(zé)周期性的釋放所有節(jié)點(diǎn)上已經(jīng)被所有節(jié)點(diǎn)收到的消息,從而達(dá)到回收各個(gè)節(jié)點(diǎn)上內(nèi)存的目的。
可靠性協(xié)議(pbcast.NAKACK2、UNICAST3)
NAKACK2
NAKACK2協(xié)議保證多播傳輸?shù)目煽啃?,是NAKACK的演進(jìn)版本,二者實(shí)現(xiàn)的功能相同,但NAKACK2更快、占用的內(nèi)存更小、定時(shí)觸發(fā)的任務(wù)更少等特點(diǎn)。
NAKACK2協(xié)議用于保證傳輸?shù)目煽啃院虵IFO順序:
- 消息可靠性:保證了一個(gè)消息會(huì)被收到,否則接收者會(huì)要求重傳
- FIFO:保證了從發(fā)送者發(fā)過(guò)來(lái)的所有消息會(huì)以相同順序到達(dá)接收方
在這種協(xié)議下,每個(gè)消息綁定一個(gè)序列號(hào),消息接收者根據(jù)序列號(hào)確保消息按正確的順序傳遞。如果接收者發(fā)現(xiàn)了一個(gè)序列號(hào)的缺失,接收者安排一個(gè)周期性的任務(wù)去要求發(fā)送者重新發(fā)送該序列號(hào)的消息,當(dāng)缺失的序列號(hào)的消息收到,則任務(wù)取消。典型配置項(xiàng)如下:
max_xmit_size:確定捆綁重發(fā)消息的大小。如果很多消息需要被重發(fā),這些重發(fā)消息可能被捆綁成一個(gè)大消息然后重發(fā)。
use_mcast_xmit:確定是否重發(fā)消息給整個(gè)集群,還是只重發(fā)消息給消息的發(fā)送者。
retransmit_timeout:重發(fā)請(qǐng)求間隔時(shí)間,接收者發(fā)現(xiàn)某一序列號(hào)消息丟失,消息重發(fā)請(qǐng)求發(fā)送給消息發(fā)送者,消息接收者等待超時(shí)后重新發(fā)送消息重發(fā)請(qǐng)求給發(fā)送者,該屬性定義了這個(gè)超時(shí)時(shí)間,而且依次遞增(第二次等待超時(shí)時(shí)間大于第一次)。該屬性在NAKACK2中已被移除,采用xmit_interval設(shè)置統(tǒng)一的間隔。
discard_delivered_msgs:確定是否在接收端清除已接收的消息。默認(rèn)情況下,消息接受者將接收到的消息保存起來(lái),當(dāng)use_mcast_xmit=true時(shí),需要從非發(fā)送節(jié)點(diǎn)請(qǐng)求重傳。如果我們只需要消息發(fā)送者重發(fā)消息,那么我們可以在接收端清除接收到的消息,該種情況我們需要設(shè)定此屬性的值為true。
其他配置參數(shù)請(qǐng)參考JGroups官方文檔。
UNICAST3
UNICAST3協(xié)議保證單播傳輸?shù)目煽啃裕⒈WCFIFO順序。
流控協(xié)議(UFC、MFC)
在JGroups中,流量控制采用基于信用系統(tǒng)(credit-based system)的實(shí)現(xiàn)方式。每當(dāng)發(fā)送者發(fā)送了X字節(jié)數(shù)據(jù),那么發(fā)送者剩余的信用字節(jié)將減少X字節(jié),接收者的信用字節(jié)增加X(jué)字節(jié)。當(dāng)發(fā)送者的信用字節(jié)下降到指定的閾值,此時(shí)需要接收者發(fā)送一些信用字節(jié)到發(fā)送者。如果發(fā)送者的信用字節(jié)耗盡,此時(shí)將被堵塞,直到收到了接收者發(fā)回的信用字節(jié)后方可繼續(xù)發(fā)送。
JGroups支持兩種類(lèi)型的流控,MFC和UFC。MFC是指Multicast Flow Control,用于控制多播數(shù)據(jù)流量,UFC是指Unicast Flow Control,用于控制單播數(shù)據(jù)流量。
分裂協(xié)議(FRAG2)
當(dāng)一個(gè)消息的大小大于某一確定的值時(shí),分裂協(xié)議將消息分裂成多個(gè)小消息,然后進(jìn)行發(fā)送;而在接收端,同樣分裂協(xié)議將分裂的消息進(jìn)行重組。不管多播還是單播發(fā)送消息,分裂協(xié)議都可以起作用。
注: