Python-based RabbitMQ and pythonrabbitmq
RabbitMQ is a complete and reusable enterprise Message System Based on AMQP. He complies with the Mozilla Public License open-source protocol. MQ is called Message Queue. MQ is a communication method for applications. Applications communicate by reading and writing messages in and out of the queue (for Application Data) without dedicated connections. Message transmission refers to the communication between programs by sending data in messages, rather than by directly calling each other. Direct calls are usually used for such remote process calls. Queuing means that applications communicate through queues. The use of the queue removes the need to receive and send applications simultaneously. Install RabbitMQ:
Install configure epel source :( see http://www.cnblogs.com/ernest-zhang/p/5714434.html) install erlang: yum-y install erlang Note: Error: Package: erlang-erts-R14B-04.3.el6.i686 (epel) Requires: libz when installing erlang. so.1 (ZLIB_1.2.2) [root @ localhost ~] # Yum whatprovides libz. so.1Loaded plugins: rhnpluginThis system is not registered with RHN. RHN support will be disabled. zlib-1.2.3-25.el6.i686: The zlib compression and decompression library # provides The compression and decompression library Repo: localMatched from: Other: libz. so.1 check found that it should be the zlib version too old, download the latest zlib-1.2.8-10.fc24.i686 from the Internet, and then use RPM after installation to solve. : Http://www.zlib.net/# http://rpmfind.net/linux/rpm2html/search.php zlib official website? Query = zlib # download the website to install rabbitMQ: yum-y install rabbitmq-server
Service rabbitmq-server start/stop start and stop the rabbitmq installation API, and then you can operate rabbitmq Based on the API
Pip install pikaoreasy_install pikaor source https://pypi.python.org/pypi/pika
Python operation on RabbitMQ release end:
Import pikaconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') # server address channel = connection. channel () channel. queue_declare (queue = 'Hi') # skip this step if a queue exists. If no queue exists, create a queue channel. basic_publish (exchange = '', routing_key = 'cc', body = 'Hello! World !!! ') Print ("[x] sent' hello, world! '") Connection. close ()
Acceptor:
Import pika # create a connection object and bind IPconnection = pika of rabbitmq. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') # create a channel object channel = connection. channel () # specify the queue in the channel. If no queue is specified in MQ, the queue is created. If yes, the channel is skipped. queue_declare (queue = 'Hi') # define the callback function def callback (ch, method, properties, body): print ('[x] Recieved % R' % body) # channel. close () # no_ack = Fales: indicates that you do not actively notify rabbitmq about the status after consumption. callback: callback function, queue: Specifies the queue channel. basic_consume (callback, queue = 'hi', no_ack = True) # channel. basic_consume (callback, queue = 'cc') print ('[*] Waiting for msg') channel. start_consuming ()
1. acknowledgment messages are not lost
No-ack = False. If the consumer fails (its channel is closed, connection is closed, or TCP connection is lost, rabbitMQ adds the task to the queue again.
- In the callback function
ch.basic_ack(delivery_tag=method.delivery_tag)
- In basic_comsume
no_ack=False
Import pikaconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. queue_declare (queue = 'Hi') # define the callback function def callback (ch, method, properties, body): print ('[x] Recieved % R' % body) # channel. close () ch. basic_ack (delivery_tag = method. delivery_tag) # no_ack = Fales: indicates that the status notification rabbitmqchannel is not automatically notified after consumption. basic_consume (callback, queue = 'hi', no_ack = False) print ('[*] Waiting for msg') channel. start_consuming ()View Codedurable message is not lost
The producer end fails to send the message and the consumer fails to receive the message. The following method will allow RabbitMQ to re-Add the message to the queue:
- In the callback function
ch.basic_ack(delivery_tag=method.delivery_tag),What the consumer needs to do
- In basic_comsume
no_ack=False,What the consumer needs to do
- Add the parameter basic_publish at the message publishing end.
properties=pika.BasicProperties(delivery_mode=2),What the producer needs to do
Import pikaconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. queue_declare (queue = 'Hi') # If yes, skip it. If no, create a queue channel. basic_publish (exchange = '', routing_key = 'hi', body = 'Hello! World !!! ', Properties = pika. BasicProperties (delivery_mode = 2) # message persistence print ("[x] sent 'hello, world! '") Connection. close ()Producer import pikaconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. queue_declare (queue = 'Hi') # define the callback function def callback (ch, method, properties, body): print ('[x] Recieved % R' % body) # channel. close () ch. basic_ack (delivery_tag = method. delivery_tag) # no_ack = Fales: indicates that the status notification rabbitmqchannel is not automatically notified after consumption. basic_consume (callback, queue = 'hi', no_ack = True) print ('[*] Waiting for msg') channel. start_consuming ()Order of obtaining consumer messages
By default, the data in the message queue is taken by the consumer in order. For example, consumer 1 gets the odd sequence from the queue and consumer 2 gets the even sequence from the queue. However, in most cases, the processing capabilities of consumer servers at the backend of the message queue are different. In this case, some servers are idle for a long time and resources are wasted, we need to change the order of obtaining the default message queue!
channel.basic_qos(prefetch_count=1)It indicates who gets the data and no longer sorts it by parity,This is what the consumer needs to do.
Import pikaconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. queue_declare (queue = 'Hi') # define the callback function def callback (ch, method, properties, body): print ('[x] Recieved % R' % body) # channel. close () ch. basic_ack (delivery_tag = method. delivery_tag) channel. basic_qos (prefetch_count = 1) # change the default acquisition order. Who will fetch it? # no_ack = Fales: indicates that rabbitmqchannel is not notified of the status after consumption. basic_consume (callback, queue = 'hi', no_ack = True) print ('[*] Waiting for msg') channel. start_consuming ()Consumer publishing and subscription
The difference between publishing and subscription is that publishing and subscription will send messages to all subscribers, and the data in the message queue will disappear once it is consumed. Therefore, when RabbitMQ implements publishing and subscription, a queue is created for each subscriber, and when the publisher publishes a message, the message is placed in all related queues.
In RabbitMQ, all messages submitted by the producer are accepted by Exchange, and then Exchange forwards messages to the Queue for storage according to specific policies. RabbitMQ provides four types of Exchange: fanout, direct, topic, and headerheader modes, which are rarely used in actual use. Only the first three modes are compared.
exchange type = fanout
Any message sent to Fanout Exchange will be forwardedExchangeAll the Queue of the Binding.
1. It can be understood as the route table mode.
2. RouteKey is not required in this mode.
3. In this mode, you need to bind Exchange and Queue in advance. One Exchange can bind multiple Queue and one Queue can be bound to multiple exchanges.
4. If the Exchange receiving the message is not bound to any Queue, the message will be discarded.
Import pikaconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. exchange_declare (exchange = 'logs _ fanout', type = 'fanout') msg = '000000' channel. basic_publish (exchange = 'logs _ fanout', routing_key = '', body = msg) print ('start sending: % s' % msg) connection. close ()Producer import pikaconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. exchange_declare (exchange = 'logs _ fanout', type = 'fanout') # randomly create a queue result = channel. queue_declare (exclusive = True) queue_name = result. method. queue # bind the relevant queue name channel. queue_bind (exchange = 'logs _ fanout', queue = queue_name) def callback (ch, method, properties, body): print ('[x] % R' % body) channel. basic_consume (callback, queue = queue_name, no_ack = True) channel. start_consuming ()Consumer
Keywords
Any message sent to Direct Exchange will be forwarded to the specified Queue in RouteKey. 1. In general, you can use the Exchange: "(the Exchange name is an empty string, which is called default Exchange below) that comes with rabbitMQ ). 2. In this mode, you do not need to bind Exchange to any binding operation. 3. A "RouteKey" is required for message transmission, which can be simply understood as the name of the queue to be sent. 4. If the queue name specified in RouteKey does not exist in the vhost, the message will be discarded. Import pikaconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. exchange_declare (exchange = 'logs _ direct_test1 ', type = 'direct') serverity = 'error' msg = '000000' channel. basic_publish (exchange = 'logs _ direct_test1 ', routing_key = serverity, body = msg) print ('start sending: % r: % R' % (serverity, msg) connection. close ()Producer import pikaconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. exchange_declare (exchange = 'logs _ direct_test1 ', type = 'direct') # randomly create a queue result = channel. queue_declare (exclusive = True) queue_name = result. method. queueserties = ['error', 'info', 'warning',] for serverity in serverities: channel. queue_bind (exchange = 'logs _ direct_test1 ', queue = que Ue_name, routing_key = serverity) print ('[***] start to accept messages! ') 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 ()Consumer 1 import pikaconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. exchange_declare (exchange = 'logs _ direct_test1 ', type = 'direct') # randomly create a queue result = channel. queue_declare (exclusive = True) queue_name = result. method. queueserties = ['error',] for serverity in serverities: channel. queue_bind (exchange = 'logs _ direct_test1 ', queue = queue_name, routing _ Key = serverity) print ('[***] start to accept the message! ') 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 ()Consumer 2
Fuzzy subscription
Any messages sent to Topic Exchange will be forwarded to all Queue that care about the specified Topic in RouteKey. this mode is complicated. In short, each queue has a topic of interest, and all messages carry a "RouteKey ), exchange will forward messages to all queues whose followers can be fuzzy matched with RouteKey. 2. This mode requires RouteKey. You may need to bind Exchange and Queue in advance. 3. when binding, you must provide a topic that the queue cares about, such as "#. log. # "indicates that the queue cares about all messages involving logs (one RouteKey is" MQ. log. the error message is forwarded to the queue ). 4. "#" indicates 0 or several keywords, and "*" indicates a keyword. For example, "log. *" can match "log. warn" and cannot match "log. warn. timeout", but "log. #" can match the two. 5. Similarly, if Exchange does not find a Queue that can match RouteKey, the message will be discarded. #! /Usr/bin/env pythonimport pikaimport sysconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. exchange_declare (exchange = 'topic _ logs', type = 'topic ') routing_key = sys. argv [1] if len (sys. argv)> 1 else 'Anonymous. info 'message = ''. join (sys. argv [2:]) or 'Hello World! 'Channel. basic_publish (exchange = 'topic _ logs', routing_key = routing_key, body = message) print ("[x] Sent % r: % r" % (routing_key, message) connection. close ()Producer #! /Usr/bin/env pythonimport pikaimport sysconnection = pika. blockingConnection (pika. connectionParameters (host = '2017. 168.0.74 ') channel = connection. channel () channel. exchange_declare (exchange = 'topic _ logs', type = 'topic ') result = channel. queue_declare (exclusive = True) queue_name = result. method. queuebinding_keys = sys. argv [1:] if not binding_keys: sys. stderr. write ("Usage: % s [binding_key]... \ n "% sys. argv [0]) sys. exit (1) for binding_key in binding_keys: channel. queue_bind (exchange = 'topic _ logs', queue = queue_name, routing_key = binding_key) 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 ()Good consumer recommended: http://hwcrazy.com/b5fce358672411e3baa0000d601c5586/group/free_open_source_project/