باستخدام RabbitMQ مع MonsterMQ الجزء 5

في الجزء السابق ، قمنا بتحسين نظام التسجيل لدينا. بدلاً من استخدام مبادل نوع fanout ، استخدمنا مبادل النوع المباشر ، مما سمح لنا بتلقي الرسائل بشكل انتقائي. على الرغم من التحسينات ، لا يزال هناك قيود على نظامنا ، على سبيل المثال ، لا يمكننا تلقي الرسائل بناءً على عدة معايير. على سبيل المثال ، في نظامنا ، قد نرغب في إعادة توجيه الرسائل بناءً ليس فقط على مستوى خطورة الرسالة ، ولكن أيضًا على مصدر الرسالة. على سبيل المثال ، كما هو الحال في أداة syslog unix، الذي يعيد توجيه الرسائل ليس فقط اعتمادًا على مستوى الخطورة (info / warn / crit ..) ، ولكن أيضًا اعتمادًا على المصدر (auth / cron / kern ...). يمكن أن يمنحنا هذا مرونة إضافية ، على سبيل المثال ، لا يمكننا استقبال سوى الرسائل المهمة من "cron" ، ولكن أيضًا جميع الرسائل من "kern". لتطبيق مثل هذا النظام ، يجب أن نتعرف على نوع أكثر تعقيدًا من المبادل - الموضوع .

مبادل نوع الموضوع


يجب أن تحتوي الرسائل المرسلة إلى مبدل نوع الموضوع على مفتاح توجيه ، وهو عبارة عن مجموعة من الكلمات مفصولة بنقاط. يمكن أن تكون الكلمات عشوائية ، لكنها عادة ما ترتبط ببعض سمات الرسالة. فيما يلي بعض الأمثلة على مفاتيح التوجيه الصالحة: stock.usd.nyse ، nyse.vmw ، quick.orange.rabbit . يقتصر المفتاح على 255 بايت.

يجب تحديد مفتاح الربط بطريقة مماثلة. يشبه توجيه الرسائل في مبادل نوع الموضوع توجيه مبادل النوع المباشر - يتم إرسال الرسالة إلى قائمة الانتظار مع مفتاح الربط المطابق لمفتاح التوجيه. ومع ذلك ، هناك اختلافان:

  1. * لا يمكن استبدال (النجمة) في مفتاح الربط إلا بكلمة واحدة
  2. يمكن استبدال # (الجنيه) في مفتاح الربط بصفر أو أكثر من الكلمات

يمكن توضيح ذلك بالصورة التالية:

صورة
(الصورة المأخوذة من موقع RabbitMQ الرسمي )

في هذا المثال ، سوف نرسل رسائل تمثل الحيوانات. تتكون مفاتيح توجيه الرسائل من ثلاث كلمات (ونقطتين). الكلمة الأولى تمثل السرعة ، والثانية تمثل اللون ، والثالثة تمثل الأنواع.

في مثالنا ، هناك طابوران متصلان بالمبادل: Q1 باستخدام مفتاح الربط "* .orange. *" و Q2 مع مفتاحي ربط "*. *. الأرنب" و "كسول. #" .

ستعني هذه الروابط التوجيه التالي:

  • Q1 مهتم بجميع حيوانات البرتقال.
  • Q2 (rabbit) (lazy)

سيتم تسليم رسالة بمفتاح التوجيه "quick.orange.rabbit" في كل من قائمتي الانتظار. سيتم أيضًا تسليم رسالة تحتوي على المفتاح "lazy.orange.elephant" إلى كليهما.

ومع ذلك ، فإن الرسالة التي تحتوي على المفتاح "quick.orange.fox" ستصل فقط في المقام الأول ، ومع المفتاح "lazy.brown.fox" في الثانية فقط. سيتم تسليم "Lazy.pink.rabbit" مرة ثانية مرة واحدة ، على الرغم من حقيقة أن مفتاح التوجيه يطابق مفتاحي الربط. لن

يدخل "Quick.brown.fox" في أي قائمة انتظار ، لأن مفتاح التوجيه لا يتطابق مع أي من مفاتيح الربط. إذا حاولت إرسال رسائل تحتوي على عدد الكلمات في مفتاح التوجيه أصغر أو أكبر (على سبيل المثال ، "برتقالي")أو "quick.orange.male.rabbit" ) من مفتاح الربط سيتم تجاهل الرسالة.

يمكن أن يتصرف مبادل نوع الموضوع مثل مبادل نوع Fanout إذا حددت # كمفتاح ربط . أو بشكل مباشر إذا لم تحدد * * أو # في مفتاح الربط ، ولكن ببساطة حدد كلمة.

وضع الكود معًا


سنستخدم مبادل نوع الموضوع لنظام التسجيل لدينا. لنبدأ بافتراض أن مفاتيح توجيه الرسائل ستبدو "source.strict" . سيكون الرمز هو نفسه تقريبًا كما في الجزء السابق ، هنا هو send.php :

try {
   $producer = \MonsterMQ\Client\Producer();

   $producer->connect('127.0.0.1', 5672);
   $producer->logIn('guest', 'guest');

   $producer->newTopicExchange('topic-logs');

   $routingKey = isset($argv[1]) && !empty($argv[1]) ? $argv[1] : 'anonymous.info';

   $message = implode(' ', array_slice($argv, 2));
   $message = empty($message) ? "Hello World!" : $message;

   $producer->publish($message, $routingKey, 'topic-logs');

   echo "\n Sent {$message} \n";
} catch(\Exception $e) {
   var_dump($e);
}

Code code -1.php

try {
   $consumer = \MonsterMQ\Client\Consumer();

   $consumer->connect('127.0.0.1', 5672);
   $consumer->logIn('guest', 'guest');

   $producer->queue('queue-1')->setExclusive()->declare();

   $consumer->newTopicExchange('topic-logs');

   $bindingKeys = array_slice($argv, 1);
   if (empty($bindingKeys)) {
      file_put_contents('php://stderr', "Usage: $argv[0] [binding_key]\n");
      exit(1);
   }

   foreach ($bindingKeys as $key) {
      $producer->queue('queue-1')->bind('topic-logs', $key);
   }

   $consumer->consume('queue-1');

  echo " \n Waiting for logs. To exit press CTRL+C\n";

   $consumer->wait(function ($message, $channelNumber) use ($consumer){
      echo "\n $message \n";
   });
} catch(\Exception $e) {
   var_dump($e);
}

Code worker-2.php

try {
   $consumer = \MonsterMQ\Client\Consumer();

   $consumer->connect('127.0.0.1', 5672);
   $consumer->logIn('guest', 'guest');

   $producer->queue('queue-2')->setExclusive()->declare();

   $consumer->newTopicExchange('topic-logs');

   $bindingKeys = array_slice($argv, 1);
   if (empty($bindingKeys)) {
      file_put_contents('php://stderr', "Usage: $argv[0] [binding_key]\n");
      exit(1);
   }

   foreach ($bindingKeys as $key) {
      $producer->queue('queue-2')->bind('topic-logs', $key);
   }

   $consumer->consume('queue-2');

  echo " \n Waiting for logs. To exit press CTRL+C\n";

   $consumer->wait(function ($message, $channelNumber) use ($consumer){
      echo "\n $message \n";
   });
} catch(\Exception $e) {
   var_dump($e);
}

لتلقي الرسائل الهامة فقط من قبل العامل الأول ، اتصل

php worker-1.php "*.critical"

لربط قائمة الانتظار التي يستخدمها العامل الثاني ، اتصل بالمبادل بمفتاحي ربط:

php worker-2.php "kern.*" "*.critical"

لإرسال رسالة ، افعل شيئًا مثل:

php send.php "kern.critical" "A critical kernel error"

جرب هذه البرامج.

All Articles