Consul

consul هو حل يتيح للفرق إدارة اتصالات الشبكة بأمان بين الخدمات عبر بيئات متعددة السحابية والبيئات المعدة مسبقًا، حيث يوفر اكتشاف الخدمة، وشبكة الخدمة، وإدارة حركة المرور، والتحديث التلقائي للبنية التحتية للشبكة وسلسلة من الوظائف الأخرى.
الوثائق الرسمية: Consul by HashiCorp
العنوان مفتوح المصدر: hashicorp/consul
Consul هو أداة اكتشاف وتسجيل خدمة مفتوحة المصدر من شركة HashiCorp، تستخدم خوارزمية انتخاب Raft، الأداة نفسها مطورة بلغة Go، لذا فإن نشرها خفيف جدًا. يتميز Consul بالخصائص التالية:
- اكتشاف الخدمة
- تسجيل الخدمة
- الفحص الصحي
- تخزين المفتاح-القيمة
- مراكز بيانات متعددة
في الواقع، يمكن لـ consul القيام بأكثر من اكتشاف الخدمة، حيث يمكنه أيضًا العمل كمركز تكوين موزع، وهناك العديد من الأدوات مفتوحة المصدر المشابهة مثل zookeeper و nacos، لن نقدمها بالتفصيل هنا.
التثبيت
بالنسبة لـ Ubuntu، يمكنك تنفيذ الأمر التالي للتثبيت باستخدام apt
$ wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
$ echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
$ sudo apt update && sudo apt install consulأو يمكنك أيضًا تنزيل حزمة التثبيت المناسبة من الموقع الرسمي Install Consul بما أن consul مطور بـ go، فإن حزمة التثبيت نفسها تحتوي فقط على ملف تنفيذي ثنائي واحد، مما يجعل التثبيت سهلًا جدًا. بعد التثبيت الناجح، نفذ الأمر التالي للتحقق من الإصدار.
$ consul versionالمخرجات الطبيعية تعني عدم وجود مشكلة
Consul v1.16.1
Revision e0ab4d29
Build Date 2023-08-05T21:56:29Z
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)البدء السريع
فيما يلي كيفية بناء عقدة consul واحدة بسرعة، عادةً ما تُستخدم العقدة الواحدة أثناء التطوير للاختبار، إذا عملت العقدة الواحدة بشكل صحيح، فمن المرجح أن يعمل نظام العقد المتعددة بدون مشاكل. بناء عقدة واحدة بسيط جدًا، يحتاج فقط إلى سطر أوامر واحد
$ consul agent -dev -bind=192.168.48.141 -data-dir=/tmp/consul -ui -node=dev01عادةً ستكون هناك مخرجات كالتالي
==> Starting Consul agent...
Version: '1.16.1'
Build Date: '2023-08-05 21:56:29 +0000 UTC'
Node ID: 'be6f6b8d-9668-f7ff-8709-ed57c72ffdec'
Node name: 'dev01'
Datacenter: 'dc1' (Segment: '<all>')
Server: true (Bootstrap: false)
Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, gRPC-TLS: 8503, DNS: 8600)
Cluster Addr: 192.168.48.141 (LAN: 8301, WAN: 8302)
Gossip Encryption: false
Auto-Encrypt-TLS: false
ACL Enabled: false
Reporting Enabled: false
ACL Default Policy: allow
HTTPS TLS: Verify Incoming: false, Verify Outgoing: false, Min Version: TLSv1_2
gRPC TLS: Verify Incoming: false, Min Version: TLSv1_2
Internal RPC TLS: Verify Incoming: false, Verify Outgoing: false (Verify Hostname: false), Min Version: TLSv1_2
==> Log data will now stream in as it occurs:
2023-08-25T17:23:33.763+0800 [DEBUG] agent.grpc.balancer: switching server: target=consul://dc1.be6f6b8d-9668-f7ff-8709-ed57c72ffdec/server.dc1 from=<none> to=<none>
2023-08-25T17:23:33.767+0800 [INFO] agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:be6f6b8d-9668-f7ff-8709-ed57c72ffdec Address:192.168.48.141:8300}]"لنشرح باختصار المعاني
agentهو أمر فرعي، وهو الأمر الأساسي لـ consul،consul agentيعني تشغيل وكيل consul جديد، كل عقدة هي وكيل.dev، هو وضع تشغيل agent، هناك ثلاثة أوضاع إجمالًا:dev،client،serverbind، عنوان الاتصال للشبكة المحلية، المنفذ الافتراضي 8301، عادةً ما تكون هذه القيمة هي عنوان الشبكة الداخلية للخادمadvertise، عنوان الاتصال للشبكة الواسعة، المنفذ الافتراضي 8302، عادةً ما تكون هذه القيمة هي عنوان الشبكة الخارجية للخادمdata-dir، دليل تخزين البياناتconfig-dir، دليل التكوين، سيقرأ consul جميع ملفات json في الدليلbootstrap، يحدد أن الخادم الحالي يدخل وضع الإقلاع، سيصوت لنفسه أثناء انتخاب raft، لا يمكن أن يكون هناك أكثر من خادم واحد في هذا الوضع في المجموعةbootstrap-expect، وهو العدد المتوقع من الخوادم في المجموعة، قبل الوصول للعدد المحدد، لن تبدأ المجموعة عملية التصويت، لا يمكن استخدامه معbootstrapفي نفس الوقت.retry-join، بعد بدء agent، سيحاول باستمرار الانضمام للعقدة المحددة، كما يدعم طرق الاكتشاف التالية من مزودي الخدمةaliyun aws azure digitalocean gce hcp k8s linode mdns os packet scaleway softlayer tencentcloud triton vsphereui، تشغيل واجهة الويب الخلفيةnode، اسم العقدة المحدد، يجب أن يكون فريدًا في المجموعة.
TIP
لمزيد من شرح معاملات agent، انتقل إلى Agents - CLI Reference | Consul | HashiCorp Developer ، تجدر الإشارة إلى أن بعض المعاملات متاحة فقط في النسخة المؤسسية.
عند التشغيل بنجاح، يمكنك زيارة 127.0.0.1:8500 لتصفح واجهة الويب.

أيقونة dev01 هي نجمة، مما يعني أنها عقدة leader.
عند الخروج، لكي تتمكن العقد الأخرى من إدراك خروج العقدة الحالية، لا يُنصح بقتل العملية بالقوة، يمكنك استخدام الأمر
consul leaveأو
consul force-leaveيمكنك أيضًا استخدام ctrl+c للسماح لوكيل consul بالخروج بأمان.
المفاهيم
هذا رسم توضيحي لمجموعة consul، ينقسم الرسم إلى جزأين، مستوى التحكم ومستوى البيانات. consul مسؤول فقط عن مستوى التحكم، وينقسم إلى مجموعة خوادم وعملاء، وتنقسم مجموعة الخوادم إلى تابعين وقائد، بشكل عام، تشكل مجموعة consul في الرسم مركز بيانات واحد. فيما يلي شرح لبعض المصطلحات
- Agent (الوكيل): أو من الأفضل تسميته عقدة، كل agent هو عملية خفية طويلة التشغيل، تعرض واجهات HTTP و DNS للعالم الخارجي، ومسؤولة عن الفحص الصحي ومزامنة الخدمة.
- Server (وكيل الخادم): كخادم consul، مسؤولياته الرئيسية هي المشاركة في انتخاب Raft، والحفاظ على حالة المجموعة، والاستجابة للاستعلامات، وتبادل البيانات مع مراكز بيانات أخرى، وإعادة توجيه الاستعلامات للقائد ومراكز البيانات الأخرى.
- Client (وكيل العميل): client عديم الحالة مقارنة بـ server، لا يشارك في انتخاب Raft، كل ما يفعله هو إعادة توجيه جميع الطلبات إلى server، الشيء الوحيد الذي يشارك فيه المتعلق بالخلفية هو نقل الشائعات عبر الشبكة المحلية (LAN gossip pool).
- Leader (القائد): leader هو قائد جميع الخوادم، ولا يمكن أن يكون هناك إلا قائد واحد، يتم انتخاب leader من خلال خوارزمية انتخاب Raft، كل قائد له فترة ولايته، خلال فترة ولايته، يجب على أي خادم آخر إخبار leader بأي طلب يتلقاه، لذا بيانات leader هي الأحدث والأحدث.
- Gossip (الشائعات): Consul مبني على Serf (منتج آخر من نفس الشركة)، ويستخدم بروتوكول gossip، هذا البروتوكول مخصص للاتصال العشوائي بين العقد، مشابه لـ UDP، يستخدم consul هذا البروتوكول للإشعار المتبادل بين مجموعات الخدمات.
- Data Center (مركز البيانات): تسمى مجموعة consul داخل شبكة محلية واحدة بمركز بيانات واحد، يدعم consul مراكز بيانات متعددة، وطريقة التواصل بين مراكز البيانات المتعددة هي WAN gossip.
TIP
للمزيد من المفردات والمصطلحات يمكنك الذهاب إلى Glossary | Consul | HashiCorp Developer للمعرفة المزيد.
في مجموعة consul، يجب التحكم بشكل صارم في عدد الخوادم، لأنها تشارك مباشرة في LAN gossip و WAN gossip، وانتخابات raft، ويجب عليها تخزين البيانات، كلما زاد عدد الخوادم، ارتفعت تكلفة الاتصال. أما عدد العملاء فلا بأس بزيادته، فهو مسؤول فقط عن إعادة التوجيه، لا يشارك في الانتخابات، ويستهلك موارد قليلة جدًا. في المجموعة في الرسم، تسجل كل خدمة نفسها في الخادم من خلال العميل، وإذا تعطل خادم، سيبحث العميل تلقائيًا عن خادم آخر متاح.
مثال بناء مجموعة
فيما يلي بناء مثال بسيط لمجموعة consul متعددة العقد، أولًا نجهز أربع أجهزة افتراضية

من بين الأجهزة الافتراضية الأربعة، ثلاثة خوادم وعميل واحد، توصي الجهة الرسمية بأن يكون عدد الخوادم فرديًا، والأفضل أن يكون ثلاثة أو أكثر. هنا سنستخدم vm00-vm02 كخوادم، و vm03 كعميل،
بالنسبة للخادم، نفذ الأمر التالي لإنشاء server agent
consul agent -server -bind=vm_address -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent_name -uiبالنسبة للعميل، نفذ الأمر التالي لإنشاء client agent
consul agent -client=0.0.0.0 -bind=vm_address -data-dir=/tmp/consul/ -node=agent_name -uiالأوامر المنفذة كالتالي
# vm00
consul agent -server -bind=192.168.48.138 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent01 -ui -bootstrap
# vm01
consul agent -server -bind=192.168.48.139 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent02 -ui -retry-join=192.168.48.138
# vm02
consul agent -server -bind=192.168.48.140 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent03 -ui -retry-join=192.168.48.138
# vm03
consul agent -bind=192.168.48.140 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent03 -ui -retry-join=192.168.48.138بعض شرح المعاملات
client،0.0.0.0تعني السماح بجميع الطلبات من أي مصدر، إذا كان هناك معامل client فقط بدون معامل server، فهذا يعني أن agent سيعمل في وضع client.
بعد تشغيل جميع الوكلاء، فإن وظيفة retry-join تعادل تنفيذ أمر join تلقائيًا، وسيعيد المحاولة عند الفشل، والوقت الافتراضي لإعادة المحاولة هو 30 ثانية
$ consul join 192.168.48.138بعد اكتمال الانضمام، جميع العقد تعرف ببعضها البعض، وبما أن vm00 حددت وضع bootstrap، فهي القائد الافتراضي، إذا لم يتم تحديد وضع bootstrap، فالعقدة المحددة في join عند انضمام جميع العقد هي القائد الافتراضي، قبل انتخاب القائد، لا يمكن للمجموعة العمل بشكل طبيعي، وستُرجع واجهة الويب 500، وبعض الأوامر لن تعمل بشكل طبيعي . إذا حددت عقدة في المجموعة وضع bootstrap، فلا يجب أن تحدد أي عقدة أخرى في المجموعة وضع bootstrap، كما لا يجب أن تستخدم العقد الأخرى معامل bootstrap-expect، وإذا استُخدم سيُعطل تلقائيًا.
في هذه اللحظة، على عقدة القائد (في الواقع يمكن عرضها من أي عقدة) نفذ الأمر لعرض معلومات أعضاء مركز البيانات
$ consul members
Node Address Status Type Build Protocol DC Partition Segment
agent01 192.168.48.138:8301 alive server 1.16.1 2 dc1 default <all>
agent02 192.168.48.139:8301 alive server 1.16.1 2 dc1 default <all>
agent03 192.168.48.140:8301 alive server 1.16.1 2 dc1 default <all>
client01 192.168.48.141:8301 alive client 1.16.1 2 dc1 default <default>- Node، أي اسم العقدة
- Address، عنوان الاتصال
- Status،
aliveتعني نشط،leftتعني غير متصل - Type، نوع agent، وضعان server و client
- Build، نسخة consul المستخدمة في هذه العقدة، يمكن لـ consul التوافق مع العقد بإصدارات مختلفة في نطاق معين
- Protocol، يشير إلى نسخة بروتوكول Raft المستخدمة، يجب أن يكون هذا البروتوكول متطابقًا في جميع العقد
- DC، Data Center، مركز البيانات، جميع العقد في المخرجات تنتمي لمركز بيانات dc1
- Partition، القسم الذي تنتمي إليه العقدة، ميزة للنسخة المؤسسية، يمكن لكل عقدة التواصل فقط مع العقد في نفس القسم
- Segment، الشريحة الشبكية التي تنتمي إليها العقدة، ميزة للنسخة المؤسسية

وبالمثل، إذا أردت خروج عقدة، يجب استخدام consul leave للخروج بأمان، وإعلام العقد الأخرى بالخروج، في حالة العقد المتعددة، الخروج الآمن للعقد مهم جدًا، لأنه يتعلق بتناسق البيانات.
TIP
تم إيقاف تشغيل جميع جدران الحماية في الأجهزة الافتراضية أثناء العرض التوضيحي، في بيئة الإنتاج الفعلية يجب تفعيلها للأمان، ولهذا يجب الانتباه لجميع المنافذ التي يستخدمها consul: Required Ports | Consul | HashiCorp Developer.
بعد ذلك، نجرب تناسق البيانات ببساطة، في الجهاز الافتراضي vm00 أضف البيانات التالية
$ consul kv put sys_confg {"name":"consul"}
Success! Data written to: sys_confgبعد الحفظ، من خلال HTTP API الوصول للعقد الأخرى ستجد أن البيانات موجودة أيضًا (القيمة value مرمزة بـ base64)
$ curl http://192.168.48.138:8500/v1/kv/sys_confg
[{"LockIndex":0,"Key":"sys_confg","Flags":0,"Value":"ewogICJuYW1lIjoiY29uc3VsIgp9","CreateIndex":2518,"ModifyIndex":2518}]
$ curl http://192.168.48.139:8500/v1/kv/sys_confg
[{"LockIndex":0,"Key":"sys_confg","Flags":0,"Value":"ewogICJuYW1lIjoiY29uc3VsIgp9","CreateIndex":2518,"ModifyIndex":2518}]
$ curl http://192.168.48.140:8500/v1/kv/sys_confg
[{"LockIndex":0,"Key":"sys_confg","Flags":0,"Value":"ewogICJuYW1lIjoiY29uc3VsIgp9","CreateIndex":2518,"ModifyIndex":2518}]في الواقع، وظيفة اكتشاف وتسجيل الخدمة التي يوفرها consul، تُبث للعقد الأخرى من خلال بروتوكول gossip، وعندما تنضم أي عقدة لمركز البيانات الحالي، ستدرك جميع العقد هذا التغيير.
مثال بناء مراكز بيانات متعددة
جهز خمسة أجهزة افتراضية، vm00-vm02 هي المجموعة من المثال السابق، وتنتمي لمركز بيانات dc1، لن نلمسها، vm03-vm04 تنتمي لمركز بيانات dc2، مركز البيانات عند بدء agent يكون افتراضيًا dc1.

TIP
هنا للعرض التوضيحي، سنقوم ببناء الخوادم فقط، ونستغني عن العملاء.
أولًا شغّل vm03، واجعلها القائد الافتراضي
$ consul agent -server -datacenter=dc2 -bind=192.168.48.141 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent04 -ui -bootstrapشغّل vm04، واجعلها تنضم تلقائيًا لعقدة vm03
$ consul agent -server -datacenter=dc2 -bind=192.168.48.142 -client=0.0.0.0 -data-dir=/tmp/consul/ -node=agent05 -ui -retry-join=192.168.48.141في هذه اللحظة، شاهد members في vm00 و vm03
# vm00-vm02
$ consul members
Node Address Status Type Build Protocol DC Partition Segment
agent01 192.168.48.138:8301 alive server 1.16.1 2 dc1 default <all>
agent02 192.168.48.139:8301 alive server 1.16.1 2 dc1 default <all>
agent03 192.168.48.140:8301 alive server 1.16.1 2 dc1 default <all>
# vm03-vm04
$ consul members
Node Address Status Type Build Protocol DC Partition Segment
agent04 192.168.48.141:8301 alive server 1.16.1 2 dc2 default <all>
agent05 192.168.48.142:8301 alive server 1.16.1 2 dc2 default <all>يمكن ملاحظة أن حقل DC مختلف، لأن هنا أجهزة افتراضية للعرض التوضيحي، فجميعها في نفس الشريحة الشبكية، في الواقع قد تكون مراكز البيانات خوادم في مواقع مختلفة. بعد ذلك اجعل أي عقدة من dc1 تنضم لأي عقدة من dc2، هنا سنجعل vm01 تنضم لـ vm03
$ consul join -wan 192.168.48.141
Successfully joined cluster by contacting 1 nodes.بعد نجاح الانضمام، نفذ الأمر لعرض أعضاء الشبكة الواسعة
$ consul members -wan
Node Address Status Type Build Protocol DC Partition Segment
agent01.dc1 192.168.48.138:8302 alive server 1.16.1 2 dc1 default <all>
agent02.dc1 192.168.48.139:8302 alive server 1.16.1 2 dc1 default <all>
agent03.dc1 192.168.48.140:8302 alive server 1.16.1 2 dc1 default <all>
agent04.dc2 192.168.48.141:8302 alive server 1.16.1 2 dc2 default <all>
agent05.dc2 192.168.48.142:8302 alive server 1.16.1 2 dc2 default <all>
$ consul catalog datacenters
dc2
dc1طالما أن أي عقدة من dc1 تنضم لأي عقدة من dc2، ستدرك جميع العقد في كلا مركزي البيانات هذا التغيير، ويمكن رؤية عقد كلا مركزي البيانات عند عرض members.
بعد ذلك، جرب إضافة بيانات KV في عقدة vm00
$ consul kv put name consul
Success! Data written to: nameفي عقدة vm01 جرب قراءة البيانات، يمكن ملاحظة أن البيانات في نفس مركز البيانات متزامنة
$ consul kv get name
consulثم اذهب لـ vm03 في مركز بيانات مختلف وجرب قراءة البيانات، ستجد أن البيانات في مراكز بيانات مختلفة غير متزامنة.
$ consul kv get name
Error! No key exists at: nameإذا كنت تريد مزامنة البيانات بين مراكز بيانات متعددة، يمكنك التعرف على hashicorp/consul-replicate: Consul cross-DC KV replication daemon.
تسجيل واكتشاف الخدمة

هناك طريقتان لتسجيل خدمة consul، التسجيل عبر ملف التكوين والتسجيل عبر API. لتسهيل الاختبار، جهزنا مسبقًا خدمة Hello World (المثال من مقالة gRPC)، ونشرنا نسختين، في مواقع مختلفة. طريقة التسجيل عبر ملف التكوين يمكن الاطلاع عليها في Register external services with Consul service discovery | Consul | HashiCorp Developer ، هنا سنقدم فقط التسجيل عبر HTTP API.
TIP
بالنسبة للخدمات المحلية (الموجودة مع عميل consul)، يمكن استخدام agent service للتسجيل مباشرة، وإلا يجب استخدام catalog register للتسجيل.
يوفر consul SDK لـ HTTP API، للأطراف بلغات أخرى انتقل إلى Libraries and SDKs - HTTP API | Consul | HashiCorp Developer للمعرفة المزيد. هنا سننزل تبعية go
go get github.com/hashicorp/consul/apiعند بدء الخدمة، يتم تسجيل الخدمة بشكل فعال في consul، وعند إيقاف الخدمة، يتم إلغاء تسجيل الخدمة من consul، فيما يلي مثال.
package main
import (
consulapi "github.com/hashicorp/consul/api"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "grpc_learn/helloworld/hello"
"log"
"net"
)
var (
server01 = &consulapi.AgentService{
// يجب أن يظل فريدًا
ID: "hello-service1",
Service: "hello-service",
// نشر نسختين، واحدة على المنفذ 8080، والأخرى على المنفذ 8081
Port: 8080,
}
)
// تسجيل الخدمة
func Register() {
client, _ := consulapi.NewClient(&consulapi.Config{Address: "192.168.48.138:8500"})
_, _ = client.Catalog().Register(&consulapi.CatalogRegistration{
Node: "hello-server",
Address: "192.168.2.10",
Service: server01,
}, nil)
}
// إلغاء تسجيل الخدمة
func DeRegister() {
client, _ := consulapi.NewClient(&consulapi.Config{Address: "192.168.48.138:8500"})
_, _ = client.Catalog().Deregister(&consulapi.CatalogDeregistration{
Node: "hello-server",
Address: "192.168.2.10",
ServiceID: server01.ID,
}, nil)
}
func main() {
Register()
defer DeRegister()
// الاستماع للمنفذ
listen, err := net.Listen("tcp", ":8080")
if err != nil {
panic(err)
}
// إنشاء خادم grpc
server := grpc.NewServer(
grpc.Creds(insecure.NewCredentials()),
)
// تسجيل الخدمة
pb.RegisterSayHelloServer(server, &HelloRpc{})
log.Println("server running...")
// التشغيل
err = server.Serve(listen)
if err != nil {
panic(err)
}
}كود العميل يستخدم محلل consul المخصص للاستعلام عن الخدمة المقابلة من مركز التسجيل، وتحويلها للعنوان الحقيقي.
package myresolver
import (
"fmt"
consulapi "github.com/hashicorp/consul/api"
"google.golang.org/grpc/resolver"
)
func NewConsulResolverBuilder(address string) ConsulResolverBuilder {
return ConsulResolverBuilder{consulAddress: address}
}
type ConsulResolverBuilder struct {
consulAddress string
}
func (c ConsulResolverBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
consulResolver, err := newConsulResolver(c.consulAddress, target, cc)
if err != nil {
return nil, err
}
consulResolver.resolve()
return consulResolver, nil
}
func (c ConsulResolverBuilder) Scheme() string {
return "consul"
}
func newConsulResolver(address string, target resolver.Target, cc resolver.ClientConn) (ConsulResolver, error) {
var reso ConsulResolver
client, err := consulapi.NewClient(&consulapi.Config{Address: address})
if err != nil {
return reso, err
}
return ConsulResolver{
target: target,
cc: cc,
client: client,
}, nil
}
type ConsulResolver struct {
target resolver.Target
cc resolver.ClientConn
client *consulapi.Client
}
func (c ConsulResolver) resolve() {
service := c.target.URL.Opaque
services, _, err := c.client.Catalog().Service(service, "", nil)
if err != nil {
c.cc.ReportError(err)
return
}
var adds []resolver.Address
for _, catalogService := range services {
adds = append(adds, resolver.Address{Addr: fmt.Sprintf(fmt.Sprintf("%s:%d", catalogService.Address, catalogService.ServicePort))})
}
c.cc.UpdateState(resolver.State{
Addresses: adds,
// استراتيجية الاقتراع
ServiceConfig: c.cc.ParseServiceConfig(
`{"loadBalancingPolicy":"round_robin"}`),
})
}
func (c ConsulResolver) ResolveNow(options resolver.ResolveNowOptions) {
c.resolve()
}
func (c ConsulResolver) Close() {
}العميل عند البدء يسجل المحلل
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/resolver"
"grpc_learn/helloworld/client/myresolver"
hello2 "grpc_learn/helloworld/hello"
"log"
"time"
)
func init() {
// تسجيل builder
resolver.Register(
// تسجيل محلل consul المخصص
myresolver.NewConsulResolverBuilder("192.168.48.138:8500"),
)
}
func main() {
// إنشاء الاتصال، بدون التحقق من التشفير
conn, err := grpc.Dial("consul:hello-service",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
panic(err)
}
defer conn.Close()
// إنشاء العميل
client := hello2.NewSayHelloClient(conn)
for range time.Tick(time.Second) {
// الاستدعاء عن بعد
helloRep, err := client.Hello(context.Background(), &hello2.HelloReq{Name: "client"})
if err != nil {
panic(err)
}
log.Printf("received grpc resp: %+v", helloRep.String())
}
}شغّل الخادم أولًا، ثم العميل، هناك خادمان يقدمان نفس الخدمة، فقط العنوان مختلف، استراتيجية موازنة الحمل للعميل هي الاقتراع، ويمكن ملاحظة من وقت السجل في الخادم أن الاستراتيجية فعالة.
2023/08/29 17:39:54 server running...
2023/08/29 21:03:46 received grpc req: name:"client"
2023/08/29 21:03:48 received grpc req: name:"client"
2023/08/29 21:03:50 received grpc req: name:"client"
2023/08/29 21:03:52 received grpc req: name:"client"
2023/08/29 21:03:54 received grpc req: name:"client"
2023/08/29 21:03:56 received grpc req: name:"client"
2023/08/29 21:03:58 received grpc req: name:"client"
2023/08/29 21:04:00 received grpc req: name:"client"هذا مثال بسيط لاستخدام consul مع gRPC لتنفيذ تسجيل واكتشاف الخدمة.
