一、rabbitmq

RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统。他遵循Mozilla Public License开源协议。

MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消 息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。

1.1 安装rabbitmq

RabbitMQ安装

1
2
3
4
5
6
7
8
安装配置epel源
   $ rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
  
安装erlang
   $ yum -y install erlang
  
安装RabbitMQ
   $ yum -y install rabbitmq-server

注意:service rabbitmq-server start/stop

安装API:

1
2
3
4
5
6
7
8
9
pip install pika
or
easy_install pika
or
源码
or
pycharm
 
https://pypi.python.org/pypi/pika

  

1.3 用python操作rabbitmq

1.3.1 基于Queue实现生产者消费者模型

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. import Queue
  4. import threading
  5.  
  6. message = Queue.Queue(10)
  7.  
  8. def producer(i):
  9. while True:
  10. message.put(i)
  11.  
  12. def consumer(i):
  13. while True:
  14. msg = message.get()
  15.  
  16. for i in range(12):
  17. t = threading.Thread(target=producer, args=(i,))
  18. t.start()
  19.  
  20. for i in range(10):
  21. t = threading.Thread(target=consumer, args=(i,))
  22. t.start()

1.3.2 rabbitmq实现消息队列

对于RabbitMQ来说,生产和消费不再针对内存里的一个Queue对象,而是某台服务器上的RabbitMQ Server实现的消息队列。

先运行消费者脚本,让它监听队列消息,然后运行生产者脚本,生产者往队列里发消息。然后消费者往队列里取消息。

  1. import pika
  2.  
  3. # ########################### 消费者 ###########################
  4.  
  5. connection = pika.BlockingConnection(pika.ConnectionParameters(
  6. host='192.168.137.208'))
  7. channel = connection.channel()
  8.  
  9. channel.queue_declare(queue='abc') # 如果队列没有创建,就创建这个队列
  10.  
  11. def callback(ch, method, propertities,body):
  12. print(" [x] Received %r" % body)
  13.  
  14. channel.basic_consume(callback,
  15. queue='abc', # 队列名
  16. no_ack=True) # 不通知已经收到,如果连接中断可能消息丢失
  17.  
  18. print(' [*] Waiting for message. To exit press CTRL+C')
  19. channel.start_consuming()
  1. import pika
  2. # ############################## 生产者 ##############################
  3. connection = pika.BlockingConnection(pika.ConnectionParameters(
  4. host='192.168.137.208'
  5. ))
  6. channel = connection.channel()
  7. channel.queue_declare(queue='abc') # 如果队列没有创建,就创建这个队列
  8. channel.basic_publish(exchange='',
  9. routing_key='abc', # 指定队列的关键字为,这里是队列的名字
  10. body='Hello World!') # 往队列里发的消息内容
  11. print(" [x] Sent 'Hello World!'")
  12. connection.close()

先运行消费者,然后再运行生产者:

  1. '''
  2. 打印:
  3. 生产者:
  4. [x] Sent 'Hello World!'
  5. 消费者:
  6. [*] Waiting for message. To exit press CTRL+C
  7. [x] Received b'Hello World!'
  8. '''

1.4 no-ack=False:rabbitmq消费者连接断了 消息不丢失

rabbitmq支持一种方式:应答。比如我从消息里拿一条消息,如果全处理完,你就不要帮我记着了。如果没处理完,突然断开了,再连接上的时候,消息队列就会重新发消息。

总结:

  • Basic.Ack 发回给 RabbitMQ 以告知,可以将相应 message 从 RabbitMQ 的消息缓存中移除。
  • Basic.Ack 未被 consumer 发回给 RabbitMQ 前出现了异常,RabbitMQ 发现与该 consumer 对应的连接被断开,之后将该 message 以轮询方式发送给其他 consumer (假设存在多个 consumer 订阅同一个 queue)。
  • 在 no_ack=true 的情况下,RabbitMQ 认为 message 一旦被 deliver 出去了,就已被确认了,所以会立即将缓存中的 message 删除。所以在 consumer 异常时会导致消息丢失。
  • 来自 consumer 侧的 Basic.Ack 与 发送给 Producer 侧的 Basic.Ack 没有直接关系

注意:

1)只有在Consumer(消费者)断开连接时,RabbitMQ才会重新发送未经确认的消息。

2)超时的情况并未考虑:无论Consumer需要处理多长时间,RabbitMQ都不会重发消息。

消息不丢失的关键代码:

1)在接收端的callback最后:

channel.basic_ack(delivery_tag=method.delivery_tag)

1
2
3
ack即acknowledge(承认,告知已收到)
也就是消费者每次收到消息,要通知一声:已经收到,如果消费者连接断了,rabbitmq会重新把消息放到队列里,下次消费者可以连接的时候,就能重新收到丢失消息。
A message MUST not be acknowledged morethan once. The receiving peer MUST validate that a non-zero delivery-tag refersto a delivered message, <br>and raise a channel exception if this is not the case.

2)除了callback函数,还要在之前设置接收消息时指定no_ack(默认False):

channel.basic_consume(callback, queue='hello', no_ack=False)

消费者:

  1. import pika

  # ########################### 消费者 ##########################

  1. connection = pika.BlockingConnection(pika.ConnectionParameters(
  2. host='10.211.55.4'))
  3. channel = connection.channel()
  4.  
  5. channel.queue_declare(queue='hello')
  6.  
  7. def callback(ch, method, properties, body):
  8. print(" [x] Received %r" % body)
  9. import time
  10. time.sleep(10)
  11. print('ok')
  12. ch.basic_ack(delivery_tag = method.delivery_tag)
  13.  
  14. channel.basic_consume(callback,
  15. queue='hello',
  16. no_ack=False)
  17.  
  18. print(' [*] Waiting for messages. To exit press CTRL+C')
  19. channel.start_consuming()

消费者断掉连接,再次连接,消息还会收到。

1.5 durable:rabbitmq服务端宕机 消息不丢失

发数据的时候,就说了:我这条数据要持久化保存。

如果rabbitmq服务端机器如果挂掉了,会给这台机器做持久化。如果启动机器后,消息队列还在。

生产者.py:

  1. import pika

# ############################## 生产者 ##############################

  1. connection = pika.BlockingConnection(pika.ConnectionParameters(host='10.211.55.4'))
  2. channel = connection.channel()
  3.  
  4. # make message persistent
  5. channel.queue_declare(queue='hello', durable=True)
  6.  
  7. channel.basic_publish(exchange='',
  8. routing_key='hello',
  9. body='Hello World!',
  10. properties=pika.BasicProperties(
  11. delivery_mode=2, # make message persistent
  12. ))
  13. print(" [x] Sent 'Hello World!'")
  14. connection.close()

消费者.py:

  1. import pika

# ########################### 消费者 ###########################

  1. connection = pika.BlockingConnection(pika.ConnectionParameters(host='10.211.55.4'))
  2. channel = connection.channel()
  3.  
  4. # make message persistent
  5. channel.queue_declare(queue='hello', durable=True)
  6.  
  7. def callback(ch, method, properties, body):
  8. print(" [x] Received %r" % body)
  9. import time
  10. time.sleep(10)
  11. print('ok')
  12. ch.basic_ack(delivery_tag = method.delivery_tag)
  13.  
  14. channel.basic_consume(callback,
  15. queue='hello',
  16. no_ack=False)
  17.  
  18. print(' [*] Waiting for messages. To exit press CTRL+C')
  19. channel.start_consuming()

测试:

1)把生产者.py执行三次。

2)然后在linux上停掉rabbitmq服务,然后再开启rabbitmq服务

1
2
3
4
5
6
[root@localhost ~]# /etc/init.d/rabbitmq-server stop
Stopping rabbitmq-server: rabbitmq-server.
 
[root@localhost ~]# /etc/init.d/rabbitmq-server start
Starting rabbitmq-server: SUCCESS
rabbitmq-server.

3)运行:消费者.py:三条消息都打印了:

1
2
3
4
5
6
7
[*] Waiting for messages. To exit press CTRL+C
 [x] Received b'Hello World!'
ok
 [x] Received b'Hello World!'
ok
 [x] Received b'Hello World!'
ok

1.6 消息获取顺序

默认消息队列里的数据是按照顺序被消费者拿走,例如:消费者1 去队列中获取 奇数 序列的任务,消费者1去队列中获取 偶数 序列的任务。

因为默认是跳着取得。第一个消费者取得很快,已经执行到20了,但是第二个消费者只取到13,可能消息执行的顺序就有问题了。

如果多个消费者,如果不想跳着取,就按消息的顺序取,而不是按着自己的间隔了。

channel.basic_qos(prefetch_count=1) 表示谁来谁取,不再按照奇偶数排列

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. __author__ = 'WangQiaomei'
  4. import pika
  5.  
  6. # ########################### 消费者 ###########################
  7. connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.137.208'))
  8. channel = connection.channel()
  9.  
  10. # make message persistent
  11. channel.queue_declare(queue='hello1')
  12.  
  13. def callback(ch, method, properties, body):
  14. print(" [x] Received %r" % body)
  15. import time
  16. time.sleep(10)
  17. print('ok')
  18. ch.basic_ack(delivery_tag = method.delivery_tag)
  19.  
  20. channel.basic_qos(prefetch_count=1)
  21.  
  22. channel.basic_consume(callback,
  23. queue='hello1',
  24. no_ack=False)
  25.  
  26. print(' [*] Waiting for messages. To exit press CTRL+C')
  27. channel.start_consuming()

1.7发布订阅

 

发布订阅原理:

1)发布订阅和简单的消息队列区别在于,发布订阅会将消息发送给所有的订阅者,而消息队列中的数据被消费一次便消失。

2)所以,RabbitMQ实现发布和订阅时,会为每一个订阅者创建一个队列,而发布者发布消息时,会将消息放置在所有相关队列中。

3)exchange 可以帮你发消息到多个队列!type设为什么值,就把消息发给哪些队列。

发布订阅应用到监控上:

模板就是写上一段脚本,放在服务器上,

客户端每5分钟,从服务端拿到监控模板,根据模板来取数据,

然后把数据结果发步到服务端的redis频道里。

服务端收到数据,1)处理历史记录 2)报警 3)dashboard显示监控信息

服务端有三处一直来订阅服务端频道(一直来收取客户端监控数据)

 

1.7.1  发布给所有绑定队列

exchange type = fanout

exchange 可以帮你发消息到多个队列,type = fanout表示:跟exchange绑定的所有队列,都会收到消息。

发布者:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. __author__ = 'WangQiaomei
  4. import pika
  5. import sys
  6. # ########################### 发布者 ###########################
  7.  
  8. connection = pika.BlockingConnection(pika.ConnectionParameters(
  9. host='192.168.137.208'))
  10. channel = connection.channel()
  11.  
  12. channel.exchange_declare(exchange='logs',
  13. type='fanout')
  14.  
  15. message = ' '.join(sys.argv[1:]) or "info: Hello World!"
  16. channel.basic_publish(exchange='logs',
  17. routing_key='',
  18. body=message)
  19. print(" [x] Sent %r" % message)
  20. connection.close()

订阅者:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. __author__ = 'WangQiaomei'
  4.  
  5. import pika
  6. # ########################### 订阅者 ###########################
  7.  
  8. connection = pika.BlockingConnection(pika.ConnectionParameters(
  9. host='192.168.137.208'))
  10. channel = connection.channel()
  11.  
  12. channel.exchange_declare(exchange='logs',
  13. type='fanout')
  14. # 随机创建队列
  15. result = channel.queue_declare(exclusive=True)
  16. queue_name = result.method.queue
  17. # 绑定
  18. channel.queue_bind(exchange='logs',
  19. queue=queue_name)
  20.  
  21. print(' [*] Waiting for logs. To exit press CTRL+C')
  22.  
  23. def callback(ch, method, properties, body):
  24. print(" [x] %r" % body)
  25.  
  26. channel.basic_consume(callback,
  27. queue=queue_name,
  28. no_ack=True)
  29.  
  30. channel.start_consuming()
  31.  
  32. '''
  33. 多次执行这个文件,就会随机生成多个队列。并且exchange都绑定这些队列。
  34. 然后发布者只需要给exchange发送消息,然后exchange绑定的多个队列都有这个消息了。订阅者就收到这个消息了。
  35. '''

1.7.2关键字发送

一个队列还可以绑定多个关键字

对一个随机队列,绑定三个关键字

再次执行,对另一个随机队列,只绑定一个关键字。

消费者:每执行一次可以生成一个队列。通过使用命令行传参的方式,来传入队列的关键字。

  1. #!/usr/bin/env python
  2. import pika
  3. import sys
  4.  
  5. connection = pika.BlockingConnection(pika.ConnectionParameters(
  6. host='localhost'))
  7. channel = connection.channel()
  8.  
  9. channel.exchange_declare(exchange='direct_logs',
  10. type='direct')
  11.  
  12. result = channel.queue_declare(exclusive=True)
  13. queue_name = result.method.queue
  14.  
  15. severities :]
  16. if not severities:
  17. sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
  18. sys.exit(1)
  19.  
  20. for severity in severities:
  21. channel.queue_bind(exchange='direct_logs',
  22. queue=queue_name,
  23. routing_key=severity)
  24.  
  25. print(' [*] Waiting for logs. To exit press CTRL+C')
  26.  
  27. def callback(ch, method, properties, body):
  28. print(" [x] %r:%r" % (method.routing_key, body))
  29.  
  30. channel.basic_consume(callback,
  31. queue=queue_name,
  32. no_ack=True)
  33.  
  34. channel.start_consuming()

容易测试的版本:

消费者1:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. __author__ = 'WangQiaomei'
  4.  
  5. import pika
  6. import sys
  7.  
  8. # ########################### 消费者1 ###########################
  9.  
  10. connection = pika.BlockingConnection(pika.ConnectionParameters(
  11. host='192.168.137.208'))
  12. channel = connection.channel()
  13.  
  14. channel.exchange_declare(exchange='direct_logs',
  15. type='direct')
  16.  
  17. result = channel.queue_declare(exclusive=True) # 随机生成队列
  18. queue_name = result.method.queue
  19.  
  20. severities ]
  21. if not severities:
  22. sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
  23. sys.exit(1)
  24.  
  25. for severity in severities:
  26. channel.queue_bind(exchange='direct_logs',
  27. queue=queue_name,
  28. routing_key=severity)
  29.  
  30. print(' [*] Waiting for logs. To exit press CTRL+C')
  31.  
  32. def callback(ch, method, properties, body):
  33. print(" [x] %r:%r" % (method.routing_key, body))
  34.  
  35. channel.basic_consume(callback,
  36. queue=queue_name,
  37. no_ack=True)
  38.  
  39. channel.start_consuming()

消费者2:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. __author__ = 'WangQiaomei'
  4.  
  5. import pika
  6. import sys
  7.  
  8. # ########################### 消费者2 ###########################
  9.  
  10. connection = pika.BlockingConnection(pika.ConnectionParameters(
  11. host='192.168.137.208'))
  12. channel = connection.channel()
  13.  
  14. channel.exchange_declare(exchange='direct_logs',
  15. type='direct')
  16.  
  17. result = channel.queue_declare(exclusive=True) # 随机生成队列
  18. queue_name = result.method.queue
  19.  
  20. severities ]
  21. for severity in severities:
  22. channel.queue_bind(exchange='direct_logs',
  23. queue=queue_name,
  24. routing_key=severity)
  25.  
  26. print(' [*] Waiting for logs. To exit press CTRL+C')
  27.  
  28. def callback(ch, method, properties, body):
  29. print(" [x] %r:%r" % (method.routing_key, body))
  30.  
  31. channel.basic_consume(callback,
  32. queue=queue_name,
  33. no_ack=True)
  34.  
  35. channel.start_consuming()

生产者:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. __author__ = 'WangQiaomei'
  4.  
  5. import pika
  6. import sys
  7.  
  8. # ############################## 生产者 ##############################
  9.  
  10. connection = pika.BlockingConnection(pika.ConnectionParameters(
  11. host='192.168.137.208'))
  12. channel = connection.channel()
  13.  
  14. channel.exchange_declare(exchange='direct_logs',
  15. type='direct')
  16.  
  17. severity = 'info'
  18. message = 'Hello World!'
  19. channel.basic_publish(exchange='direct_logs',
  20. routing_key=severity,
  21. body=message)
  22. print(" [x] Sent %r:%r" % (severity, message))
  23. connection.close()
  24.  
  25. '''
  26. 同时运行消费者1,消费者2,然后修改生产者的关键字,运行生产者。
  27. 当生产者:severity = 'info',则消费者1收到消息,消费者2没收到消息
  28. 当生产者:severity = 'error',则消费者1、消费者2 都收到消息
  29. '''

1.7.2  模糊匹配

exchange type = topic

在topic类型下,可以让队列绑定几个模糊的关键字,之后发送者将数据发送到exchange,exchange将传入”路由值“和 ”关键字“进行匹配,匹配成功,则将数据发送到指定队列。

  • # 表示可以匹配 0 个 或 多个 字符
  • *  表示只能匹配 一个 任意字符
1
2
3
发送者路由值              队列中
old.boy.python          old.*  -- 不匹配
old.boy.python          old.#  -- 匹配

消费者:

  1. #!/usr/bin/env python
  2. import pika
  3. import sys
  4. # ############################## 消费者 ##############################
  5. connection = pika.BlockingConnection(pika.ConnectionParameters(
  6. host='192.168.137.208'))
  7. channel = connection.channel()
  8.  
  9. channel.exchange_declare(exchange='topic_logs',
  10. type='topic')
  11.  
  12. result = channel.queue_declare(exclusive=True)
  13. queue_name = result.method.queue
  14.  
  15. binding_keys = "*.orange.*"
  16.  
  17. for binding_key in binding_keys:
  18. channel.queue_bind(exchange='topic_logs',
  19. queue=queue_name,
  20. routing_key=binding_key)
  21.  
  22. print(' [*] Waiting for logs. To exit press CTRL+C')
  23.  
  24. def callback(ch, method, properties, body):
  25. print(" [x] %r:%r" % (method.routing_key, body))
  26.  
  27. channel.basic_consume(callback,
  28. queue=queue_name,
  29. no_ack=True)
  30.  
  31. channel.start_consuming()

生产者:

  1. #!/usr/bin/env python
  2. import pika
  3. import sys
  4. # ############################## 生产者 ##############################
  5. connection = pika.BlockingConnection(pika.ConnectionParameters(
  6. host='192.168.137.208'))
  7. channel = connection.channel()
  8.  
  9. channel.exchange_declare(exchange='topic_logs',
  10. type='topic')
  11.  
  12. # routing_key = 'abc.new.qiaomei.old'
  13. routing_key = 'neworangeold'
  14. message = 'Hello World!'
  15. channel.basic_publish(exchange='topic_logs',
  16. routing_key=routing_key,
  17. body=message)
  18. print(" [x] Sent %r:%r" % (routing_key, message))
  19. connection.close()
  20.  
  21. '''
  22. #.orange.# 匹配:new.orange.old neworangeold
  23. *.orange.* 匹配:neworangeold,不匹配:new.orange.old
  24. '''

1.8 saltstack原理实现

saltstack:zeromq:放到内存里的,会更快,会基于这个做rcp

openstack:大量使用:rabbitmq

saltstack上有master,有三个队列。,让三个客户端每个人取一个队列的任务

saltstack的原理:

1)发一条命令ifconfig,想让所有nginx主机组的机器,都执行。

2)在master我们可以发命令给exchange,nginx总共有10台服务器,创建10个带有nginx关键字的10个队列,

3)master随机生成队列,md5是一个队列的名字,exchange把命令和md5这个消息推送到nginx关键字的队列里。

4)nginx10台服务器从队列中取出消息,执行命令,并且把主机名和执行的结果返回给这个队列里。

5)master变为消费者,取出队列里的主机名和执行结果,并打印到终端上。

服务器1:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. __author__ = 'WangQiaomei'
  4.  
  5. import pika
  6. import sys
  7.  
  8. # ########################### 消费者1 ###########################
  9.  
  10. connection = pika.BlockingConnection(pika.ConnectionParameters(
  11. host='192.168.137.208'))
  12. channel = connection.channel()
  13.  
  14. channel.exchange_declare(exchange='direct_logs',
  15. type='direct')
  16.  
  17. result = channel.queue_declare(exclusive=True) # 随机生成队列
  18. queue_name = result.method.queue
  19.  
  20. severities = ]
  21. if not severities:
  22. sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
  23. sys.exit(1)
  24.  
  25. for severity in severities:
  26. channel.queue_bind(exchange='direct_logs',
  27. queue=queue_name,
  28. routing_key=severity)
  29.  
  30. print(' [*] Waiting for logs. To exit press CTRL+C')
  31.  
  32. def callback(ch, method, properties, body):
  33. print(" [x] %r:%r" % (method.routing_key, body))
  34. queue_md5=body.decode().split(",")[1]
  35. hostname = 'nginx1'
  36. channel.queue_declare(queue=queue_md5) # 如果队列没有创建,就创建这个队列
  37. channel.basic_publish(exchange='',
  38. routing_key=queue_md5, # 指定队列的关键字为,这里是队列的名字
  39. body='%s|cmd_result1' %hostname) # 往队列里发的消息内容
  40.  
  41. channel.basic_consume(callback,
  42. queue=queue_name,
  43. no_ack=True)
  44.  
  45. channel.start_consuming()

服务器2:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. __author__ = 'WangQiaomei'
  4.  
  5. import pika
  6. import sys
  7.  
  8. # ########################### 消费者2 ###########################
  9.  
  10. connection = pika.BlockingConnection(pika.ConnectionParameters(
  11. host='192.168.137.208'))
  12. channel = connection.channel()
  13.  
  14. channel.exchange_declare(exchange='direct_logs',
  15. type='direct')
  16.  
  17. result = channel.queue_declare(exclusive=True) # 随机生成队列
  18. queue_name = result.method.queue
  19.  
  20. severities = ["nginx"]
  21.  
  22. for severity in severities:
  23. channel.queue_bind(exchange='direct_logs',
  24. queue=queue_name,
  25. routing_key=severity)
  26.  
  27. print(' [*] Waiting for logs. To exit press CTRL+C')
  28.  
  29. def callback(ch, method, properties, body):
  30. print(" [x] %r:%r" % (method.routing_key, body))
  31. queue_md5=body.decode().split(",")[1]
  32. hostname = 'nginx2'
  33. channel.queue_declare(queue=queue_md5) # 如果队列没有创建,就创建这个队列
  34. channel.basic_publish(exchange='',
  35. routing_key=queue_md5, # 指定队列的关键字为,这里是队列的名字
  36. body='%s|cmd_result2' %hostname) # 往队列里发的消息内容
  37.  
  38. channel.basic_consume(callback,
  39. queue=queue_name,
  40. no_ack=True)
  41.  
  42. channel.start_consuming()

master:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. __author__ = 'WangQiaomei'
  4.  
  5. import pika
  6. import sys
  7. import hashlib
  8.  
  9. # ############################## 生产者 ##############################
  10.  
  11. connection = pika.BlockingConnection(pika.ConnectionParameters(
  12. host='192.168.137.208'))
  13. channel = connection.channel()
  14.  
  15. channel.exchange_declare(exchange='direct_logs',
  16. type='direct')
  17.  
  18. severity = 'nginx'
  19. m2 = hashlib.md5()
  20. m2.update(severity.encode('utf-8'))
  21. md5_security=m2.hexdigest()
  22. print('md5_security:',md5_security)
  23. message = 'cmd,%s' % md5_security
  24.  
  25. channel.basic_publish(exchange='direct_logs',
  26. routing_key=severity,
  27. body=message)
  28. print(" [x] Sent %r:%r" % (severity, message))
  29. connection.close()
  30.  
  31. #################################3
  32. connection = pika.BlockingConnection(pika.ConnectionParameters(
  33. host='192.168.137.208'))
  34. channel = connection.channel()
  35.  
  36. channel.queue_declare(queue=md5_security) # 如果队列没有创建,就创建这个队列
  37.  
  38. def callback(ch, method, propertities,body):
  39. print(" [x] Received %r" % body)
  40.  
  41. channel.basic_consume(callback,
  42. queue=md5_security, # 队列名
  43. no_ack=True) # 不通知已经收到,如果连接中断消息就丢失
  44.  
  45. print(' [*] Waiting for message. To exit press CTRL+C')
  46. channel.start_consuming()

打印:

1
2
3
4
5
6
7
8
9
10
11
12
'''
服务器1,和服务器2都打印:
 [*] Waiting for logs. To exit press CTRL+C
 [x] 'nginx':b'cmd,ee434023cf89d7dfb21f63d64f0f9d74'
 
master打印:
md5_security: ee434023cf89d7dfb21f63d64f0f9d74
 [x] Sent 'nginx':'cmd,ee434023cf89d7dfb21f63d64f0f9d74'
 [*] Waiting for message. To exit press CTRL+C
 [x] Received b'nginx2|cmd_result2'
 [x] Received b'nginx1|cmd_result1'
'''

python操作RabbitMQ(不错)的更多相关文章

  1. Python操作RabbitMQ

    RabbitMQ介绍 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现的产品,RabbitMQ是一个消息代理,从“生产者”接收消息并传递消 ...

  2. Python之路【第九篇】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

    Python之路[第九篇]:Python操作 RabbitMQ.Redis.Memcache.SQLAlchemy   Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用 ...

  3. python - 操作RabbitMQ

    python - 操作RabbitMQ     介绍 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议.MQ全称为Mess ...

  4. 文成小盆友python-num12 Redis发布与订阅补充,python操作rabbitMQ

    本篇主要内容: redis发布与订阅补充 python操作rabbitMQ 一,redis 发布与订阅补充 如下一个简单的监控模型,通过这个模式所有的收听者都能收听到一份数据. 用代码来实现一个red ...

  5. Python之路第十二天,高级(4)-Python操作rabbitMQ

    rabbitMQ RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列(M ...

  6. Python菜鸟之路:Python基础-Python操作RabbitMQ

    RabbitMQ简介 rabbitmq中文翻译的话,主要还是mq字母上:Message Queue,即消息队列的意思.rabbitmq服务类似于mysql.apache服务,只是提供的功能不一样.ra ...

  7. Python操作 RabbitMQ、Redis、Memcache

    Python操作 RabbitMQ.Redis.Memcache Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数 ...

  8. Python 【第六章】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  9. Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

随机推荐

  1. CSS3 Loading进度条加载动画特效

    在线演示 本地下载

  2. zabbix监控nginx的性能

    1.nginx配置 需要使用zabbix监控nginx,首先nginx需要配置ngx_status,在nginx的配置文件中加入红框中的配置,然后重启nginx如下图所示: location /ngx ...

  3. poj2431 一直Wa

    在遍历加油站的时候,会将经过的x加油站放入优先队列,之后将x从数组中删掉,即用最后一个加油站来替代x:这时如果不 “i--”,则会漏掉检查原来的stop[n-1],则可能造成错误. if(stop[i ...

  4. zabbix安装配置agent程序之agent配置文件详解

    安装zabbix-agent http://repo.zabbix.com/zabbix/3.2/rhel/6/x86_64/ 下载:zabbix-agent-3.2.0-1.el6.x86_64.r ...

  5. Spring_通过 FactoryBean 配置 Bean

    beans-factorybean.xml <?xml version="1.0" encoding="UTF-8"?><beans xmln ...

  6. 并发-ThreadLocal源码分析

    ThreadLocal源码分析 参考: http://www.cnblogs.com/dolphin0520/p/3920407.html https://www.cnblogs.com/coshah ...

  7. unidbnavigator提示汉化

  8. make install报错

    今天,在运行公司内核的机器上,编译标准内核,结果提示: 问题原因: 原来安装新内核的时候,会与原内核比较,如果缺少了某些模块,就会提示”ERROR: modinfo: could not find m ...

  9. Linux 增加对外开放的端口

    查看端口是否对外开放 /etc/init.d/iptables status # /etc/init.d/iptables status 表格:filter Chain INPUT (policy A ...

  10. C语言中单引号和双引号

    写惯了python对单引号和双引号都混了.. C语言中的单引号和双引号含义迥异,用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值,因此,采用ASCII字符集的 ...