Menggunakan RabbitMQ dengan MonsterMQ Bagian 5

Pada bagian sebelumnya, kami meningkatkan sistem logging kami. Alih-alih menggunakan penukar jenis fanout, kami menggunakan penukar jenis langsung, yang memungkinkan kami menerima pesan secara selektif. Meskipun ada perbaikan, sistem kami masih memiliki keterbatasan, misalnya, kami tidak dapat menerima pesan berdasarkan beberapa kriteria. Misalnya, di sistem kami, kami mungkin ingin mengarahkan ulang pesan tidak hanya berdasarkan tingkat keparahan pesan, tetapi juga pada sumber pesan. Misalnya, seperti pada alat unix syslog, yang mengalihkan pesan tidak hanya tergantung pada tingkat keparahan (info / warn / crit ..), tetapi juga tergantung pada sumbernya (auth / cron / kern ...). Ini dapat memberi kami fleksibilitas tambahan, misalnya, kami hanya dapat menerima pesan penting dari 'cron', tetapi juga semua pesan dari 'kern'. Untuk menerapkan sistem seperti itu, kita harus berkenalan dengan jenis penukar - topik yang lebih kompleks .

Penukar tipe topik


Pesan yang dikirim ke penukar jenis topik harus memiliki kunci perutean, yang merupakan sekumpulan kata yang dipisahkan oleh titik-titik. Kata-kata bisa arbitrer, tetapi biasanya dikaitkan dengan beberapa fitur pesan. Berikut adalah beberapa contoh kunci perutean yang valid: stock.usd.nyse , nyse.vmw , quick.orange.rabbit . Kuncinya terbatas pada 255 byte.

Kunci pengikat harus ditentukan dengan cara yang sama. Perutean pesan dalam penukar jenis topik mirip dengan perutean penukar jenis langsung - pesan dikirim ke antrian dengan kunci penjilidan yang cocok dengan kunci perutean. Namun, ada dua perbedaan:

  1. * (tanda bintang) pada kunci yang mengikat hanya dapat diganti dengan satu kata
  2. # (pon) pada kunci penjilidan dapat diganti dengan nol atau lebih banyak kata

Ini dapat diilustrasikan oleh gambar berikut:

gambar
(gambar diambil dari situs web resmi RabbitMQ )

Dalam contoh ini, kami akan mengirim pesan yang mewakili hewan. Tombol perutean pesan terdiri dari tiga kata (dan dua titik). Kata pertama mewakili kecepatan, yang kedua mewakili warna, dan yang ketiga mewakili spesies.

Dalam contoh kami, dua antrian terhubung ke penukar: Q1 dengan kunci penjilidan "* .orange. *" Dan Q2 dengan dua kunci penjilid "*. *. Kelinci" dan "malas. #" .

Tautan ini berarti perutean berikut:

  • Q1 tertarik pada semua hewan oranye.
  • Q2 (rabbit) (lazy)

Sebuah pesan dengan kunci perutean β€œquick.orange.rabbit” akan dikirimkan di kedua antrian. Pesan dengan kunci "lazy.orange.elephant" juga akan dikirimkan ke keduanya.

Namun, pesan dengan tombol "quick.orange.fox" hanya akan menjadi yang pertama, dan dengan kunci "lazy.brown.fox" hanya di yang kedua. "Lazy.pink.rabbit" akan dikirimkan untuk kedua kalinya, meskipun faktanya kunci perutean cocok dengan kedua kunci yang mengikat.

"Quick.brown.fox" tidak akan masuk ke antrian apa pun, karena kunci perutean tidak cocok dengan salah satu kunci yang mengikat. Jika Anda mencoba mengirim pesan dengan jumlah kata di tombol perutean lebih kecil atau lebih besar (misalnya, "oranye"atau "quick.orange.male.rabbit" ) daripada di kunci yang mengikat pesan akan dibuang.

Penukar jenis topik dapat berperilaku seperti penukar jenis kipas jika Anda menetapkan # sebagai kunci pengikat . Atau langsung jika Anda tidak menentukan * * atau # di kunci yang mengikat , tetapi cukup menunjukkan sebuah kata.

Menyatukan kode


Kami akan menggunakan penukar jenis topik untuk sistem pencatatan kami. Mari kita mulai dengan asumsi bahwa kunci perutean pesan kita akan terlihat seperti "source.strict . " Kode akan hampir sama dengan di bagian sebelumnya, di sini adalah 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);
}

Pekerja kode -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);
}

Pekerja kode -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);
}

Untuk hanya menerima pesan penting oleh pekerja pertama, hubungi

php worker-1.php "*.critical"

Untuk mengikat antrian yang digunakan pekerja kedua, panggil exchanger dengan dua kunci ikat:

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

Untuk mengirim pesan, lakukan sesuatu seperti:

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

Eksperimen dengan program-program ini.

All Articles