في الجزء السابق ، قمنا بتحسين نظام التسجيل لدينا. بدلاً من استخدام مبادل نوع fanout ، استخدمنا مبادل النوع المباشر ، مما سمح لنا بتلقي الرسائل بشكل انتقائي. على الرغم من التحسينات ، لا يزال هناك قيود على نظامنا ، على سبيل المثال ، لا يمكننا تلقي الرسائل بناءً على عدة معايير. على سبيل المثال ، في نظامنا ، قد نرغب في إعادة توجيه الرسائل بناءً ليس فقط على مستوى خطورة الرسالة ، ولكن أيضًا على مصدر الرسالة. على سبيل المثال ، كما هو الحال في أداة syslog unix، الذي يعيد توجيه الرسائل ليس فقط اعتمادًا على مستوى الخطورة (info / warn / crit ..) ، ولكن أيضًا اعتمادًا على المصدر (auth / cron / kern ...). يمكن أن يمنحنا هذا مرونة إضافية ، على سبيل المثال ، لا يمكننا استقبال سوى الرسائل المهمة من "cron" ، ولكن أيضًا جميع الرسائل من "kern". لتطبيق مثل هذا النظام ، يجب أن نتعرف على نوع أكثر تعقيدًا من المبادل - الموضوع .مبادل نوع الموضوع
يجب أن تحتوي الرسائل المرسلة إلى مبدل نوع الموضوع على مفتاح توجيه ، وهو عبارة عن مجموعة من الكلمات مفصولة بنقاط. يمكن أن تكون الكلمات عشوائية ، لكنها عادة ما ترتبط ببعض سمات الرسالة. فيما يلي بعض الأمثلة على مفاتيح التوجيه الصالحة: stock.usd.nyse ، nyse.vmw ، quick.orange.rabbit . يقتصر المفتاح على 255 بايت.يجب تحديد مفتاح الربط بطريقة مماثلة. يشبه توجيه الرسائل في مبادل نوع الموضوع توجيه مبادل النوع المباشر - يتم إرسال الرسالة إلى قائمة الانتظار مع مفتاح الربط المطابق لمفتاح التوجيه. ومع ذلك ، هناك اختلافان:- * لا يمكن استبدال (النجمة) في مفتاح الربط إلا بكلمة واحدة
- يمكن استبدال # (الجنيه) في مفتاح الربط بصفر أو أكثر من الكلمات
يمكن توضيح ذلك بالصورة التالية:
(الصورة المأخوذة من موقع 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.phptry {
$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.phptry {
$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"
جرب هذه البرامج.