gossipod
1.0.0
以 Rust 編寫的非同步可擴展弱一致感染式進程組成員協定 (SWIM) 實作。
警告
免責聲明:該項目正在進行中,尚未準備好投入生產。程式碼庫可能包含錯誤或不完整的功能。謹慎使用。歡迎回饋和貢獻,謝謝!
io_uring
運行時(SWIM:Basic)
+ (SWIM+Inf.)
+ (SWIM+Inf.+Susp.)
並擴展以包含 Hashicorp Research 的 Lifeguard 功能Gossipod 使用 3 種類型的訊息: PING
、 PING-REQ
和BROADCAST
(其中包括JOIN
、 LEAVE
、 SUSPECT
、 ALIVE
和CONFIRM
子類型)。 PING
和PING-REQ
訊息是系統基於 SWIM 的故障檢測機制的核心,透過在此過程中附帶訊息傳播來促進持續的狀態交換。當狀態發生變化時,無論是透過自願請求還是定期故障檢測,系統都會使用BROADCAST
訊息隨機傳播此資訊。網路中的每個節點都維護一個化身號,從零開始,只能由節點本身遞增。此數字對於管理其他節點本地成員清單中的節點狀態至關重要,並可作為反駁其他節點懷疑(SWIM+Inf.+Susp.)
的手段。這種設計使 Gossipod 能夠在分散式或去中心化網路中實現高效且有彈性的分散式狀態管理和故障檢測,平衡對最新資訊、衝突解決和系統可靠性的需求。
透過擴展,Lifeguard 提供了尚未合併到當前版本的 Gossipod 中的附加實作功能,這些功能得到 Hashicorp 成員清單的完全支援。我計劃在未來的版本中整合這些功能。
序列圖
參與者 N1 作為節點 1
參與者 N2 作為節點 2
參與者 N3 作為節點 3
參與者 Nx 作為節點 x(隨機)
N1、Nx 的註釋:透過捎帶進行探測與訊息傳播
N1->>N2:PING(附帶資訊)
N2->>N1:ACK(附帶資訊)
N1->>N3:PING-REQ(對於 N2)
N3->>N2:平
N2->>N3:ACK
N3->>N1:ACK(間接)
關於 N1,Nx 的註解:狀態變化傳播
N1->>Nx:廣播(離開/加入/懷疑/確認)
Nx->>N2:PING(附帶狀態變更)
N2->>N3:PING(附帶狀態變更)
N1、Nx 的註解:故障偵測與恢復
N1->>N2:PING(無回應)
N1->>N3:PING-REQ(對於 N2)
N3->>N2:PING(無回應)
N3->>N1:NACK
N1->>Nx:廣播(懷疑 N2)
N2 的注意事項:N2 收到 SUSPECT 訊息
N2->>N2:增加化身數
N2->>Nx:廣播(ALIVE,有新的化身編號)
alt N2 成功反駁
Nx->>N1:PING(搭載 ALIVE N2)
關於 N1 的註解:將 N2 狀態更新為存活
否則N2沒有及時反駁
N1->>Nx:廣播(確認 N2 失敗)
結尾
要查看 Gossipod 的實際效果,請查看./examples
目錄,其中包含許多演示。下面您可以執行兩個不同的 gossipod 實例,指定不同的連接埠位址和節點名稱
> cargo run -p ping_node -- --name=NODE_1 --port=7948
> cargo run -p pong_node -- --name=NODE_2 --port=7947 --join-addr=127.0.0.1:7948
let config = GossipodConfigBuilder :: new ( )
. with_name ( & args . name )
. with_port ( args . port )
. with_addr ( args . ip . parse :: < Ipv4Addr > ( ) . expect ( "Invalid IP address" ) )
. with_probing_interval ( Duration :: from_secs ( 1 ) )
. with_ack_timeout ( Duration :: from_millis ( 500 ) )
. with_indirect_ack_timeout ( Duration :: from_secs ( 1 ) )
. with_suspicious_timeout ( Duration :: from_secs ( 5 ) )
. with_network_type ( NetworkType :: LAN )
. build ( )
. await ? ;
let gossipod = Gossipod :: new ( config ) . await ? ;
# [ derive ( Clone , Debug , Serialize , Deserialize , PartialEq , Eq , Hash ) ]
struct Metadata {
region : String ,
datacenter : String ,
}
impl NodeMetadata for Metadata { }
let metadata = Metadata {
region : "aws-west-1" . to_string ( ) ,
datacenter : "dc1" . to_string ( ) ,
} ;
let gossipod = Gossipod :: with_metadata ( config , metadata ) . await ? ;
以下是如何在應用程式中使用 Gossipod 的基本範例:
// Configuration
let config = GossipodConfigBuilder :: new ( )
. with_name ( & args . name )
. with_port ( args . port )
. with_addr ( args . ip . parse :: < Ipv4Addr > ( ) . expect ( "Invalid IP address" ) )
. with_probing_interval ( Duration :: from_secs ( 1 ) )
. with_ack_timeout ( Duration :: from_millis ( 500 ) )
. with_indirect_ack_timeout ( Duration :: from_secs ( 1 ) )
. with_suspicious_timeout ( Duration :: from_secs ( 5 ) )
. with_network_type ( NetworkType :: LAN )
. build ( )
. await ? ;
// New instance
let gossipod = Arc :: new ( Gossipod :: new ( config . clone ( ) ) . await ? ) ;
// Start Gossipod
tokio :: spawn ( gossipod . clone ( ) . start ( ) ) ;
// Wait for Gossipod to start
while !gossipod . is_running ( ) . await {
time :: sleep ( Duration :: from_millis ( 100 ) ) . await ;
}