Tutorial on the official website of RabbitMQ --- route, official website of rabbitmq --- route
(Use python client pika 0.9.8)
In the previous tutorial, we built a simple log system. We can broadcast log messages to many recipients.
In this tutorial, we will add a feature to it-we will subscribe to only one message subset as possible. For example, we can direct only error messages to log files (saved to disk space) and print all log messages on the console.
Bind
In the previous example, we have created a binding. You can call code like this again:
channel.queue_bind(exchange=exchange_name, queue=queue_name)
Binding is a relationship between exchange and queue. This can be simply read: the queue is interested in messages from this exchange.
An additional routing_key parameter can be used for binding. To avoid confusion with a basic_publish parameter, a bound key is called. This is how we use one key to create a binding:
channel.queue_bind(exchange=exchange_name,queue=queue_name, routing_key='black')
The binding key indicates the exchange type. Fanout type exchange, we use the previous, simply ignore its value.
Direct exchange
In the previous tutorial, our log system broadcasts all messages to all consumers. We want to extend it to allow messages to be filtered based on their services. For example, we may want to write scripts to only receive serious error log messages, and do not waste disk space on warning and information logs.
We use a fanout type exchange, which does not give us much scalability-it can only broadcast unconsciously.
We will replace it with direct type exchange. The routing algorithm behind direct exchange is simple-a message enters the queue of a message routing_key that matches the binding key.
To clarify this, consider the following settings:
In this setting, we can see that exchange X of the direct type has two queues bound to it. The first queue uses the BIND key orange to bind, the second queue has two bindings, one with the BIND key black and the other with the green.
Setting a message to be published to exchange using a route key orange will be routed to the queue Q1. Use the route key black or green to enter Q2. All messages are discarded.
Multiple bindings
It is perfectly legal to bind multiple queues with the same binding key. In our example, we can bind a key black between X and Q1. In that example, the direct type of exchange will be similar to fanout and broadcast messages to all matching queues. A black message using the route key will be sent to Q1 and Q2.
Production Log
We will use this mode for our log system. Single fanout we will send messages to a direct type exchange. We will provide the log severity as a route key. In this way, you can select the severity of the script you want to receive. We first focus on production logs.
We always need to first create exchange:
channel.exchange_declare(exchange='direct_logs', type='direct')
And we are going to send a message:
channel.basic_publish(exchange='direct_logs',routing_key=severity,body=message)
For simplified things, we recommend that the 'severity 'be either 'info', 'warning', or 'error.
Subscription
Receiving messages takes effect just as in the previous tutorial. With an exception, we will create a binding for each degree of severity that we are interested in.
result=channel.queue_declare(exclusive=True)queue_name = result.method.queuefor severity in severities: channel.queue_bind(exchange='direct_logs', queue=queue_name, routing_key=severity)
Code together
Emit_log_direct.py code:
#!/usr/bin/env pythonimport pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='direct_logs',type='direct')severity = sys.argv[1] if len(sys.argv) > 1 else 'info'message = ' '.join(sys.argv[2:]) or 'Hello World!'channel.basic_publish(exchange='direct_logs', routing_key=severity, body=message)print "[x] sent %r:%r" %(severity, message)connection.close()
Receive_logs_direct.py code:
#!/usr/bin/env pythonimport pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.exchange_declare(exchange='direct_logs', type='direct')result = channel.queue_declare(exclusive=True)queue_name = result.method.queueseverities = sys.argv[1:]if not severities: print >> sys.stderr, "Usage : %s [info] [warning] [error]" %(sys.argv[0],) sys.exit(1) for severity in severities: channel.queue_bind(exchange='direct_logs', queue=queue_name, routing_key=severity) print '[*] waiting for logs. To exit press CTRL+C'def callback(ch, method, properties, body): print "[x] %r:%r" %(method, routing_key, body,) channel.basic_consume(callback, queue=queue_name, no_ack=True)channel.start_consuming()