Usando RabbitMQ con MonsterMQ Parte 5

En la parte anterior, mejoramos nuestro sistema de registro. En lugar de usar el intercambiador de tipo fanout, utilizamos el intercambiador de tipo directo, que nos permitió recibir mensajes selectivamente. A pesar de las mejoras, nuestro sistema todavía tiene limitaciones, por ejemplo, no podemos recibir mensajes basados ​​en varios criterios. Por ejemplo, en nuestro sistema, es posible que queramos redirigir mensajes basados ​​no solo en el nivel de gravedad del mensaje, sino también en el origen del mensaje. Por ejemplo, como en la herramienta syslog unix, que redirige los mensajes no solo según el nivel de gravedad (info / warn / crit ..), sino también según la fuente (auth / cron / kern ...). Esto puede darnos flexibilidad adicional, por ejemplo, podemos recibir solo mensajes críticos de 'cron', pero también todos los mensajes de 'kern'. Para implementar dicho sistema, debemos familiarizarnos con un tipo de intercambiador más complejo: el tema .

Intercambiador de tipo de tema


Los mensajes enviados al intercambiador de tipo de tema deben tener una clave de enrutamiento, que es un conjunto de palabras separadas por puntos. Las palabras pueden ser arbitrarias, pero generalmente están asociadas con alguna característica del mensaje. Estos son algunos ejemplos de claves de enrutamiento válidas: stock.usd.nyse , nyse.vmw , quick.orange.rabbit . La clave está limitada a 255 bytes.

La clave de enlace debe especificarse de manera similar. El enrutamiento de mensajes en el intercambiador de tipo de tema es similar al enrutamiento directo del intercambiador: el mensaje se envía a la cola con la clave de enlace que coincide con la clave de enrutamiento. Sin embargo, hay dos diferencias:

  1. * (asterisco) en la clave de enlace solo se puede reemplazar con una palabra
  2. # (libra) en la clave de enlace se puede reemplazar por cero o más palabras

Esto se puede ilustrar con la siguiente imagen:

imagen
(imagen tomada del sitio web oficial de RabbitMQ )

En este ejemplo, enviaremos mensajes que representan animales. Las claves de enrutamiento de mensajes constan de tres palabras (y dos puntos). La primera palabra representa velocidad, la segunda representa color y la tercera representa especie.

En nuestro ejemplo, hay dos colas conectadas al intercambiador: Q1 con la clave de enlace "* .orange. *" Y Q2 con dos claves de enlace "*. *. Rabbit" y "lazy. #" .

Estos enlaces significarán la siguiente ruta:

  • Q1 está interesado en todos los animales naranjas.
  • Q2 (rabbit) (lazy)

Se entregará un mensaje con la clave de enrutamiento "quick.orange.rabbit" en ambas colas. También se enviará a ambos un mensaje con la clave "lazy.orange.elephant" .

Sin embargo, el mensaje con la clave "quick.orange.fox" solo aparecerá en primer lugar, y con la clave "lazy.brown.fox" solo en el segundo. "Lazy.pink.rabbit" se entregará por segunda vez una vez, a pesar de que la clave de enrutamiento coincide con ambas claves vinculantes.

"Quick.brown.fox" no entrará en ninguna cola, ya que la clave de enrutamiento no coincide con ninguna de las claves de enlace. Si intenta enviar mensajes con el número de palabras en la clave de enrutamiento menor o mayor (por ejemplo, "naranja"o "quick.orange.male.rabbit" ) que en la clave de enlace el mensaje será descartado.

El intercambiador de tipos de tema puede comportarse como un intercambiador de tipos de despliegue si especifica # como la clave de enlace . O como directo si no especifica * * o # en la clave de enlace , sino que simplemente indica una palabra.

Poniendo el código juntos


Utilizaremos el intercambiador de tipos de tema para nuestro sistema de registro. Comencemos con la suposición de que nuestras claves de enrutamiento de mensajes se verán como "source.strict" . El código será casi el mismo que en la parte anterior, aquí está 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);
}

Código trabajador-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);
}

Código trabajador-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);
}

Para recibir solo mensajes críticos del primer trabajador, llame al

php worker-1.php "*.critical"

Para enlazar la cola que usa el segundo trabajador, llame al intercambiador con dos teclas de enlace:

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

Para enviar un mensaje, haga algo como:

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

Experimente con estos programas.

All Articles