参考:

http://www.rabbitmq.com/tutorials/tutorial-one-python.html

http://www.rabbitmq.com/tutorials/tutorial-three-python.html

1 基本

RabbitMQ是一个消息中间件(message broker),它接受和转发消息。类似邮局的功能。

使用的术语:

  Procucer-发送消息的就是生产者。

  Queue-消息存储在队列中,队列就是一个大型的消息缓存。多个生产者可以将消息发送给一个队列,多个消费者可以尝试从一个队列接受数据。

  Consume-消费者是等待接受消息的程序

note:producer,consumer,broker在绝大部分应用中,分布在不同的主机上。

2 第一个程序-Hello World

生产者向队列‘hello’发送消息,生产者从队列接受消息。

中间的box是queue--维持在消费者一端的消息缓存。

2.1 send.py

  1. import pika
  2.  
  3. #向一个指定地址上的broker创立连接
  4. conncetion = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
  5. channel = conncetion.channel()
  6.  
  7. #发送消息之前需要确认接收端队列存在
  8. #如果发送数据到一个不存在的位置,RabbitMQ会丢掉消息
  9. #在这里我们声明一个hello队列来投递消息
  10. channel.queue_declare('hello')
  11.  
  12. #现在发送一个消息到hello这个队列。
  13. #在RabbitMQ中,一个消息无法直接发送带队列,而是需要通过一个exchange。
  14. #目前只需要知道如何使用一个默认的由一个空字符串认证的exchange,它允许指定消息要发到哪个队列
  15. #队列名在route-key参数中指定
  16. channel.basic_publish(exchange='',routing_key='hello',body='Hello World')
  17.  
  18. #退出程序之前需要确认网络缓存被清空,并且消息被投递到RabbitMQ。可以优雅地关闭连接
  19. conncetion.close()

  

2.2 receive.py

  1. import pika
  2.  
  3. #连接到RabbitMQ Server
  4. conncetion = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
  5. channel = conncetion.channel()
  6.  
  7. #确认接收端队列存在
  8. channel.queue_declare('hello')
  9.  
  10. #从队列接受消息较为复杂,它通过向队列订阅一个回调函数来工作
  11. #每当我们接受一个消息,pika库会调用回调函数
  12. #在这个case中,函数会打印消息内容
  13. def callback(ch, method, properties, body):
  14. print("Received %r" % body)
  15.  
  16. #告知RabbitMQ,指定的回调函数要从hello队列中接受消息
  17. #如果订阅的queue不存在,这一步会失败
  18. channel.basic_consume(callback,queue='hello',no_ack=True)
  19.  
  20. #这个函数会一直等待数据,并在需要时运行回调函数
  21. print('waiting for maeeage')
  22. channel.start_consuming()

 

2.3 运行程序

  当消费者启动,就会开始等待从hello队列接受消息,并且循环接受。每当队列中产生数据,就会到达消费者。

2.4 消费者轮训机制

  如果从同一个队列获取数据的消费者有多个,那就会默认使用轮训机制获取数据。

2.5 no_ack参数

  在应用场景中,生产者相当于客户端,消费者相当于服务端。生产者使用basix_publish函数发送数据到队列,然后消费者使用basic_consume从队列中获取数据,并调用回调函数对数据进行处理。

  在流程上,生产者发送消息到队列,然后消费者使用回调函数处理完后,默认情况下,在basic_consume函数中,no_ack=False,就是会向生产者发送清楚处理完成确认消息。生产者收到该消息,就会删除队列中的消息。

  如果消费者在处理过程中宕机,RabbitMQ检测到sokcet连接断了,就会把消息发到下一个轮训点。

  在第二大点的案例中,加上了no_ack=True,就是消费者不会向生产者发送处理完确认信息。这样,如果消费者在处理过程中宕机,生产者也会删除队列中的消息。这适合于不看重处理结果的请求。

2.6 持久化队列

  当RabbitMQ服务宕机,队列信息就会丢失,在声明队列时加上持久化参数,会把队列保存(里面的消息依然不会保存)

  1. channel.queue_declare('hello',durable=True)

  会把消息也持久化,需要在生产者的basic_publish函数里加一个参数

  1. channel.basic_publish(exchange='',routing_key='hello',body='Hello World',
  2. properties=pika.BasicProperties(delivery_mode=2)
  3. )

  

2.7 channel.basic_qos(prefetch_count=1)

3 Publish/Subscribe

  在RabbitMQ的消息模型中,核心特征就是,生产者永远不会直接向队列发送任何消息,甚至大部分时候生产者都不知道一个消息是否会被投递到队列中。

  生产者只能把消息发给exchange。exchange一面从生产者接受消息,另一面把消息推送给队列。exchange必须准确知道该如何处理所收到的消息。exchange type就是来定义处理方式的规则。

  

  在第二大点,exchange='',这是默认的exchange,会按照route_key里的queue名去发送消息(如果该queue存在的话)

  fanout exchange很简单,就是把自己从生产者收到的所有消息广播给它绑定的所有队列。

3.1 publish.py

  1. import pika
  2. message='i am jabbok'
  3. connect = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
  4. channel = connect.channel()
  5.  
  6. #声明一个fanout的exchange类型,取名‘logs’
  7. #exchange会向所有与自己绑定的queue广播自己收到的消息
  8. channel.exchange_declare(exchange='logs',exchange_type='fanout')
  9.  
  10. #当exchange='',会根据route_key的值去查找队列
  11. #而fanout类型的exchange,是向所有绑定的队列发送消息。所以route_key=''
  12. channel.basic_publish(exchange='logs',routing_key='',body=message)
  13.  
  14. channel.close()

  

3.2 subscribe.py

  1. import pika,time
  2.  
  3. conncetion = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
  4. channel = conncetion.channel()
  5. channel.exchange_declare(exchange='logs',exchange_type='fanout')
  6.  
  7. #在本例中,只需要当前的消息,所以每次连接队列都会清空
  8. #为此创建的队列使用的是随机名,所以队列声明里不需要queue参数
  9. #加上exclusive唯一参数,与该随机名queue连接的生产者断开连接,该queue删除
  10. #result.method.queue包含一个随机的队列名
  11. result = channel.queue_declare(exclusive=True)
  12. queue_name = result.method.queue
  13.  
  14. #绑定exchange和队列,就是告诉exchange把消息发给哪个queue
  15. #这里queue是个随机名
  16. channel.queue_bind(exchange='logs',queue=queue_name)
  17.  
  18. def callback(ch, method, properties, body):
  19. print("Received %r" % body)
  20.  
  21. channel.basic_consume(callback,queue=queue_name,no_ack=True)
  22.  
  23. print('waiting for maeeage')
  24. channel.start_consuming()

  

3.3 运行

  消费发布后,如果对端没有订阅者,队列马上删除。这时再运行订阅,也收不到消息。

  在第二大点,同一个消息,消费者是轮训接受。但在订阅发布模型中,所有订阅者都会收到同一个消息。

  

  

pika消息中间件模块的更多相关文章

  1. 消息中间件JMS(一)

    1.JMS入门 1.1消息中间件 模块之间的依赖也称之为耦合.而耦合越多,之后的维护工作就越困难.那么如果改善系统模块调用关系.减少模块之间的耦合呢?我们接下来就介绍一种解决方案----消息中间件. ...

  2. rabbitmq(中间消息代理)在python中的使用

    在之前的有关线程,进程的博客中,我们介绍了它们各自在同一个程序中的通信方法.但是不同程序,甚至不同编程语言所写的应用软件之间的通信,以前所介绍的线程.进程队列便不再适用了:此种情况便只能使用socke ...

  3. Python与RabbitMQ交互

    RabbitMQ 消息队列 成熟的中间件RabbitMQ.ZeroMQ.ActiveMQ等等 RabbitMQ使用erlang语言开发,使用RabbitMQ前要安装erlang语言 RabbitMQ允 ...

  4. python之celery的使用(一)

    前段时间需要使用rabbitmq做写缓存,一直使用pika+rabbitmq的组合,pika这个模块虽然可以很直观地操作rabbitmq,但是官方给的例子太简单,对其底层原理了解又不是很深,遇到很多坑 ...

  5. python之celery使用详解一

    前段时间需要使用rabbitmq做写缓存,一直使用pika+rabbitmq的组合,pika这个模块虽然可以很直观地操作rabbitmq,但是官方给的例子太简单,对其底层原理了解又不是很深,遇到很多坑 ...

  6. pyquery:轻松、灵活的处理html

    介绍 pyquery是一个专门用来解析html的库,从名字很容易想到jQuery,没错,这完全是仿照jQuery的语法实现的.如果用过jQuery,那么pyquery也很容易上手 初始化html py ...

  7. 消息中间件Client模块划分

    上图是之间讨论确定的系统架构(后续内容会按照这个架构来叙述),其中: 客户端包含Producer和Consumer两大块 客户端需要和NameServer交互来获取元数据 客户端需要和Broker交互 ...

  8. python的pika模块操作rabbitmq

    上一篇博文rabbitmq的构架和原理,了解了rabbitmq的使用原理,接下来使用python的pika模块实现使用rabbitmq. 环境搭建 安装python,不会的请参考Linux安装配置py ...

  9. 关于python中pika模块的问题

    工作中经常用到rabbitmq,而用的语言主要是python,所以也就经常会用到python中的pika模块,但是这个模块的使用,也给我带了很多问题,这里整理一下关于这个模块我在使用过程的改变历程已经 ...

随机推荐

  1. 64位CentOs7源码安装mysql-5.6.35过程分享

    首先安装依赖包,避免在安装过程中出现问题 [root@bogon liuzhen]# yum -y install gcc gcc-c++[root@bogon liuzhen]# yum -y in ...

  2. JAVA的WebService规范JAX-WS

    JAX-WS的服务端.客户端双方传输数据使用的SOAP消息格式封装数据. 一.下载apache-cxf-3.1.4.zip. 二.编写服务端 1.编写一个Web Service用来传输参数的类 pac ...

  3. 李雅普诺夫函数 LyapunovFunction 李雅普诺夫意义下的稳定性

    https://zh.wikipedia.org/zh-hans/李亞普諾夫函數 李雅普诺夫函数(Lyapunov function)是用来证明一动力系统或自治微分方程稳定性的函数.其名称来自俄罗斯数 ...

  4. java里类方法和实例方法

    实例方法相对于静态方法(或者叫类方法)而言没有 static 前缀类般方法被对象拥有(也称之实例方法原因)特点定义时候前面没有 static 前缀本类直接调用时候必须也实例方法内否则调用前必须先实例出 ...

  5. ajax访问json文件缓存问题

    ajax访问json文件,json文件改动,访问的时候也不能及时看到改动后的内容. 这是因为浏览器缓存的原因. 在这时候就需要清除浏览器的缓存或者加上一个标记,让ajax访问文件的时候知道这是一个新的 ...

  6. PLSQL 安装说明

    PLSQL安装说明. 1.安装oracle 11g ,2030端口设置防火墙例外.2.PLSQL Developer 9.0.0.1601是绿色版,复制到本地即可.3.PLSQL->Tools- ...

  7. myeclipse8.6注册码

     loveyLR8ZC-855550-69545856608357821   

  8. 2016-5-23 jsp

    1.table的边框:rules这个参数,它有三个值(cols,rows,none),当rules=cols时,表格会隐藏横向的分隔线,也就是我们只能看到表格的列:当rules=rows时,就隐藏了纵 ...

  9. parquet文件格式——本质上是将多个rows作为一个chunk,同一个chunk里每一个单独的column使用列存储格式,这样获取某一row数据时候不需要跨机器获取

    Parquet是Twitter贡献给开源社区的一个列数据存储格式,采用和Dremel相同的文件存储算法,支持树形结构存储和基于列的访问.Cloudera Impala也将使用Parquet作为底层的存 ...

  10. [原创]java调用PageOffice生成word

    一.在开发OA办公或与文档相关的Web系统中,难免会遇到动态生成word文档的需求,为了解决工作中遇到导出word文档的需求,前一段时间上网找了一些资料,在word导出这方面有很多工具可以使用,jac ...