ملاحظة : لا يزال في مرحلة ألفا. قد تتغير واجهات برمجة التطبيقات.
(يتم عكس هذا الريبو على https://codeberg.org/flowerinthenight/zgroup).
zgroup هي مكتبة Zig يمكنها إدارة عضوية المجموعة واكتشاف فشل الأعضاء. ويستخدم مزيجًا من نشر المعلومات بأسلوب القيل والقال الخاص ببروتوكول SWIM، وخوارزمية انتخاب القائد الخاصة بشركة Raft (مطروحًا منها إدارة السجل) لتتبع تغييرات المجموعة.
أحد الأهداف الرئيسية لـ zgroup هو أن تكون قادرًا على تتبع المجموعات ذات الأحجام التي يمكن أن تتغير ديناميكيًا بمرور الوقت (مثل عمليات نشر Kubernetes، ومجموعات مثيلات GCP، ومجموعات AWS Autoscaling، وما إلى ذلك) مع الحد الأدنى من التبعيات وتحميل الشبكة. جميع أعمالي السابقة ذات الصلة حتى الآن، تعتمد على بعض الخدمات الخارجية (انظر المغزل، التحوط)، باستخدام نبض القلب التقليدي، لتحقيق ذلك. عادةً ما تعاني هذه التقنية النابضة من زيادة أحجام الحمولة (بما يتناسب مع أحجام المجموعات) مع زيادة حجم المجموعات. لكنني أردت نظامًا لا يعاني من هذا التأثير الجانبي. أدخل نشر معلومات نمط العدوى الخاصة بـ SWIM. يمكنه استخدام حجم حمولة ثابت بغض النظر عن حجم المجموعة. يستخدم SWIM مجموعة من PING
s و INDIRECT-PING
s و ACK
s لاكتشاف فشل الأعضاء أثناء استخدام هذه الرسائل نفسها لنشر تحديثات العضوية (بروتوكول القيل والقال). حاليًا، تستخدم zgroup فقط بروتوكول التحقيق المباشر الخاص بـ SWIM؛ لا ينفذ البروتوكول الفرعي Suspicion بشكل كامل (حتى الآن).
في الوقت الحالي، يستخدم zgroup حمولة واحدة بحجم 64 بايت لجميع رسائله، بما في ذلك اختيار القائد (انظر أدناه).
كنت أرغب أيضًا في الحصول على نوع من القدرة على انتخاب القائد دون الاعتماد على خدمة قفل خارجية. في الوقت الحالي، تستخدم zgroup البروتوكول الفرعي لخوارزمية انتخاب القائد الخاص بـ Raft (بدون إدارة السجل) لتحقيق ذلك. يجب أن أشير إلى أن خوارزمية انتخاب قائد Raft تعتمد على العضوية المستقرة حتى تعمل بشكل صحيح، لذا فإن انتخاب قائد zgroup هو أساس أفضل جهد فقط؛ لا يزال من الممكن حدوث انقسام الدماغ بينما لا يزال حجم الكتلة يتغير. تتم إضافة حراس كود إضافيين لتقليل انقسام الدماغ في هذه السيناريوهات ولكن لم يتم التخلص منه بالكامل. في حالة الاستخدام (والاختبار) الخاصة بي، تكون التغييرات التدريجية في حجم المجموعة مستقرة في الغالب، في حين أن التغييرات المفاجئة ذات الدلتا ذات الحجم الكبير ليست كذلك. على سبيل المثال، قفزة كبيرة ومفاجئة من ثلاث عقد (الحد الأدنى لحجم مجموعة z) إلى مائة، على سبيل المثال، بسبب القياس التلقائي، من شأنه أن يسبب انقسام الدماغ. ومع ذلك، بمجرد تحقيق الحجم المستهدف، سيتم دائمًا انتخاب قائد واحد.
ملاحظة حول نطاق المهلة العشوائي لـ Raft أثناء اختيار القائد: يتتبع قائد zgroup متوسطات زمن انتقال ping ويحاول ضبط نطاق المهلة وفقًا لذلك لاستيعاب تغييرات حجم المجموعة مع مرور الوقت.
لكي تنضم العقدة إلى مجموعة موجودة، فإنها تحتاج إلى عنوان الانضمام. بينما يعرض zgroup وظيفة join()
لهذا الغرض، فإنه يوفر أيضًا آلية رد اتصال، مما يوفر للمتصلين عنوان انضمام. يمكن بعد ذلك تخزين هذا العنوان في متجر خارجي لتستخدمه العقد الأخرى. داخليًا، تستخدم zgroup العقدة ذات أعلى عنوان IP(v4) في المجموعة.
يتم توفير نموذج ثنائي لإظهار طريقة لاستخدام المكتبة. هناك طريقتان لتشغيل العينة:
# Build the sample binary:
$ zig build --summary all
# Run the 1st process. The expected args look like:
#
# ./zgroup groupname member_ip:port [join_ip:port]
#
# Run the first process (join to self).
$ ./zig-out/bin/zgroup group1 0.0.0.0:8080 0.0.0.0:8080
# Then you can run additional instances.
# Join through the 1st process/node (different terminal):
$ ./zig-out/bin/zgroup group1 0.0.0.0:8081 0.0.0.0:8080
# Join through the 2nd process/node (different terminal):
$ ./zig-out/bin/zgroup group1 0.0.0.0:8082 0.0.0.0:8081
# Join through the 1st process/node (different terminal):
$ ./zig-out/bin/zgroup group1 0.0.0.0:8083 0.0.0.0:8080
# and so on...
إذا تم تكوينه، يستخدم النموذج الثنائي خدمة مجانية، https://keyvalue.immanuel.co/، كمخزن لعنوان الانضمام.
# Build the sample binary:
$ zig build --summary all
# Generate UUID:
$ uuidgen
{output}
# Run the 1st process. The expected args look like:
#
# ./zgroup groupname member_ip:port
#
# Run the first process:
$ ZGROUP_JOIN_PREFIX={output} ./zig-out/bin/zgroup group1 0.0.0.0:8080
# Add a second node (different terminal):
$ ZGROUP_JOIN_PREFIX={output} ./zig-out/bin/zgroup group1 0.0.0.0:8081
# Add a third node (different terminal):
$ ZGROUP_JOIN_PREFIX={output} ./zig-out/bin/zgroup group1 0.0.0.0:8082
# Add a fourth node (different terminal):
$ ZGROUP_JOIN_PREFIX={output} ./zig-out/bin/zgroup group1 0.0.0.0:8083
# and so on...
يتم توفير نموذج لملف نشر Kubernetes لتجربة zgroup على عمليات نشر Kubernetes. قبل النشر، تأكد من تحديث متغير البيئة ZGROUP_JOIN_PREFIX
، كما يلي:
# Generate UUID:
$ uuidgen
{output}
# Update the 'value' part with your output.
...
- name: ZGROUP_JOIN_PREFIX
value: " {output} "
...
# Deploy to Kubernetes:
$ kubectl create -f k8s.yaml
# You will notice some initial errors in the logs.
# Wait for a while before the K/V store is updated.
يتم توفير نموذج نصي لبدء التشغيل لتجربة zgroup على GCP MIG. قبل النشر، تأكد من تحديث قيمة ZGROUP_JOIN_PREFIX
في البرنامج النصي، كما يلي:
# Generate UUID:
$ uuidgen
{output}
# Update the 'value' part of ZGROUP_JOIN_PREFIX with your output.
...
ZGROUP_JOIN_PREFIX={output} ./zgroup group1 ...
# Create an instance template:
$ gcloud compute instance-templates create zgroup-tmpl
--machine-type e2-micro
--metadata=startup-script= ' ' " $( cat startup-gcp-mig.sh ) " ' '
# Create a regional MIG:
$ gcloud compute instance-groups managed create rmig
--template zgroup-tmpl --size 3 --region {your-region}
# You can view the logs through:
$ tail -f /var/log/messages
يتم توفير نموذج نصي لبدء التشغيل لتجربة zgroup على AWS ASG. قبل النشر، تأكد من تحديث قيمة ZGROUP_JOIN_PREFIX
في البرنامج النصي، كما يلي:
# Generate UUID:
$ uuidgen
{output}
# Update the 'value' part of ZGROUP_JOIN_PREFIX with your output.
...
ZGROUP_JOIN_PREFIX={output} ./zgroup group1 ...
# Create a launch template. ImageId here is Amazon Linux, default VPC.
# (Added newlines for readability. Might not run when copied as is.)
$ aws ec2 create-launch-template
--launch-template-name zgroup-lt
--version-description version1
--launch-template-data '
{
"UserData":" ' " $( cat startup-aws-asg.sh | base64 -w 0 ) " ' ",
"ImageId":"ami-0f75d1a8c9141bd00",
"InstanceType":"t2.micro"
} '
# Create the ASG:
$ aws autoscaling create-auto-scaling-group
--auto-scaling-group-name zgroup-asg
--launch-template LaunchTemplateName=zgroup-lt,Version= ' 1 '
--min-size 3
--max-size 3
--availability-zones {target-zone}
# You can view the logs through:
$ [sudo] journalctl -f
للحصول على الأعضاء الحاليين في المجموعة، يمكنك تجربة شيء مثل:
const members = try fleet . getMembers ( gpa . allocator ());
defer members . deinit ();
for ( members . items , 0 .. ) | v , i | {
defer gpa . allocator (). free ( v );
log . info ( "member[{d}]: {s}" , .{ i , v });
}
الجزء الصعب من استخدام zgroup هو تكوين المهلات لتحسين نشر الحالة وتقاربها. تم اختبار التنفيذ الحالي فقط داخل شبكة محلية.
العلاقات العامة هي موضع ترحيب.