تنفيذ بروتوكول عضوية مجموعة العمليات (SWIM) غير المتزامن والقابل للتوسع والمتسق بشكل ضعيف والمكتوب بلغة Rust.
تحذير
إخلاء المسؤولية: هذا المشروع قيد التنفيذ وليس جاهزًا للإنتاج بعد. قد تحتوي قاعدة التعليمات البرمجية على أخطاء أو ميزات غير كاملة. استخدم بحذر. ردود الفعل والمساهمات موضع ترحيب، شكرا!.
io_uring
عبر Tokio (SWIM:Basic)
+ (SWIM+Inf.)
+ (SWIM+Inf.+Susp.)
وتوسيع نطاقه ليشمل ميزات من Lifeguard بواسطة Hashicorp Research يستخدم Gossipod ثلاثة أنواع من الرسائل: 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: ناك
N1->>Nx: البث (المشتبه به N2)
ملاحظة حول N2: يتلقى N2 رسالة مشتبه بها
N2->>N2: زيادة رقم التجسد
N2->>Nx: البث (مباشر برقم التجسد الجديد)
البديل 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 ;
}