注意:在rabbitmq中,可以存在多个exchange,exchange只是负责接收消息,然后消息必须发送到给queue中,如果没有queue,消息就丢失了,exchange就相当于交换机,不负责存消息,queue是必须声明的,所以exchange负责转发,queue负责接收

回调函数:

你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件

普通函数与回调函数的区别:

    • 对普通函数的调用:
      调用程序发出对普通函数的调用后,程序执行立即转向被调用函数执行,直到被调用函数执行完毕后,再返回调用程序继续执行。从发出调用的程序的角度看,这个过程为“调用-->等待被调用函数执行完毕-->继续执行”

    • 对回调函数调用:
      调用程序发出对回调函数的调用后,不等函数执行完毕,立即返回并继续执行。这样,调用程序执和被调用函数同时在执行。当被调函数执行完毕后,被调函数会反过来调用某个事先指定函数,以通知调用程序:函数调用结束。这个过程称为回调(Callback),这正是回调函数名称的由来。

    • 比如你显示器不亮了,你不知道怎么弄,那你就问在外地干IT的大表哥,你大表哥告诉你该怎么弄,然后需要你自己来操作。

      你大表哥知道怎么弄,但是不会自己去弄,而是由你去弄。

      换句话说,你大表哥实现了修理你显示器的方法,但他不会自己去调用,而是由你去调用。

      那么你大表哥告诉你的修机器的方法就是回调函数。

最简单的队列通信

send端

  1. import pika
  2. #创建一个类似于socket连接
  3. #credentials = pika.PlainCredentials('zcq', '123456')
  4. # connection = pika.BlockingConnection(pika.ConnectionParameters(host=url_1,
  5. # credentials=credentials, ssl=ssl, port=port))
  6. # connection = pika.BlockingConnection(pika.ConnectionParameters(
  7. # host='192.168.12.112',credentials=credentials))
  8. connection = pika.BlockingConnection(pika.ConnectionParameters(
  9. host='localhost'))
  10. channel = connection.channel() #商议好协议
  11.  
  12. # 声明queue
  13. channel.queue_declare(queue='zcq',durable=True) #声明Q durable为设置为持久化 Q名必须唯一
  14.  
  15. # n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
  16. channel.basic_publish(exchange='',
  17. routing_key='zcq', #send msg to this queue 发送到哪个Q里面
  18. body='zhaichaoqun', #消息内容
  19. properties=pika.BasicProperties(
  20. delivery_mode=2, # make message persistent 持久化 如果Q设置为持久化 消息也必须设置持久化
  21. )
  22. )
  23. print(" [x] Sent 'Hello World!2'")
  24. connection.close()

send端开头部分注释: 是设置密码验证,如果rabbitmq 开启了用户认证形式,就必须指定用户名密码

recv端

  1. import pika
  2. import time
  3.  
  4. #如果有密码就用密码认证
  5. #credentials = pika.PlainCredentials('alex', 'alex3714')
  6. # connection = pika.BlockingConnection(pika.ConnectionParameters(
  7. # host='192.168.12.112',credentials=credentials))
  8. connection = pika.BlockingConnection(pika.ConnectionParameters(
  9. host='localhost'))
  10. channel = connection.channel()
  11. channel.queue_declare(queue='zcq',durable=True)
  12.  
  13. def callback(ch, method, properties, body):
  14. print(ch, method, properties)
  15.  
  16. print(" [x] Received %r" % body)
  17. time.sleep(1)
  18.  
  19. channel.basic_consume(callback,
  20. queue='zcq',
  21. #no_ack=True #ack知识
  22. )
  23. channel.basic_qos(prefetch_count=1) #相当于负载均衡
  24. print(' [*] Waiting for messages. To exit press CTRL+C')
  25. channel.start_consuming()

如果Rabbit只管按顺序把消息发到各个消费者身上,不考虑消费者负载的话,很可能出现,一个机器配置不高的消费者那里堆积了很多消息处理不完,同时配置高的消费者却一直很轻松。为解决此问题,可以在各个消费者端,配置perfetch=1,意思就是告诉RabbitMQ在我这个消费者当前消息还没处理完的时候就不要再给我发新消息了

消息的发送和订阅

exchange在定义的时候是有类型的,以决定到底是哪些Queue符合条件

有三种类型:

fanout: 所有bind到此exchange的queue都可以接收到消息

direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息

topic:所有符合routingKey(也可以是一个表达式)的 routingKey的bind的queue可以接收消息

  表达式: # 代表一个或多个字符, *代表任何字符,如果routingKey直接设置为#,那这里的topic类型,就相当于使用了fanout

     例如:  #.a 会匹配到a.a  aa.a   aaa.a 等

        *.a  会匹配到A.a  b.a  asas.a 等

Exchange:根据Routing key 转发消息到对应的Message Queue中

RoutingKey: 用于Exchange 判断哪些消息需要发送到对应的Message Queue

消息订阅和发布(exchange type=fanout)

send端

  1. import pika
  2. import sys
  3.  
  4. #生产者
  5. #
  6. #如果需要密码 这里指定密码
  7. #credentials = pika.PlainCredentials('guest','guest')
  8. #connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost',credentials=credentials ))
  9. connection = pika.BlockingConnection(pika.ConnectionParameters(
  10. host='localhost'))
  11.  
  12. channel = connection.channel() #channel 绑定的意思,即routing key,就好比,每个邮局把信件送到你家邮箱的一条路线
  13.  
  14. channel.exchange_declare(exchange='zcq',
  15. type='fanout')
  16.  
  17. message = ' '.join(sys.argv[1:]) or 'hellow-----'
  18.  
  19. channel.basic_publish(exchange='zcq',
  20. routing_key='',
  21. body=message)
  22.  
  23. print('--%s--'%message)
  24. connection.close()

运行:python3 rabbit-fanout.py info test          发送info test 到订阅的消费者中

recv端

  1. import pika
  2.  
  3. # credentials = pika.PlainCredentials('guest','guest')
  4. connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
  5.  
  6. channel = connection.channel()
  7.  
  8. channel.exchange_declare(exchange='zcq',type='fanout')
  9.  
  10. result=channel.queue_declare(exclusive=True) #不指定Q名,rabbit会随机分配一个名字,这里会在使用queue的消费着断开后,自动删除q
  11.  
  12. queue_name = result.method.queue #得到队列的名字
  13.  
  14. channel.queue_bind(exchange='zcq',queue=queue_name)
  15. def callback(ch, method, properties, body):
  16. #def callback(ch,method,properties,body):
  17. print('[x] %r' %body)
  18.  
  19. channel.basic_consume(callback,queue=queue_name)
  20.  
  21. channel.start_consuming()

运行:python3 rabbit-fanout-recv.py info       recv端接受info信息  

有选择的接受消息(exchange type=direct)

send端

  1. import pika
  2. import sys
  3.  
  4. connection = pika.BlockingConnection(pika.ConnectionParameters(
  5. host='localhost'))
  6. channel = connection.channel()
  7.  
  8. channel.exchange_declare(exchange='direct_logs', #设置exchange名称
  9. type='direct') #类型
  10.  
  11. severity = sys.argv[1] if len(sys.argv) > 1 else 'info'
  12. message = ' '.join(sys.argv[2:]) or 'Hello World!'
  13.  
  14. channel.basic_publish(exchange='direct_logs',
  15. routing_key=severity,
  16. body=message)
  17. print(" [x] Sent %r:%r" % (severity, message))
  18. connection.close() #

运行:>python3 rabbit-direct-send.py info aa   注释:send端将 sys.argv[1] 值设置为routingKey    后面aa为信息

recv端

  1. import pika
  2. import sys
  3.  
  4. connection = pika.BlockingConnection(pika.ConnectionParameters(
  5. host='localhost'))
  6. channel = connection.channel()
  7.  
  8. channel.exchange_declare(exchange='direct_logs', #指定exchange名称
  9. type='direct')
  10.  
  11. result = channel.queue_declare(exclusive=True) ##不指定Q名,rabbit会随机分配一个名字,这里会在使用queue的消费着断开后,自动删除q
  12. queue_name = result.method.queue #得到Q名称 recv端必须指定queue
  13.  
  14. severities = sys.argv[1:]
  15. if not severities:
  16. sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
  17. sys.exit(1)
  18.  
  19. for severity in severities: #循环 severities 列表 得到用户输入值 然后传入到routing_key 来绑定
  20. channel.queue_bind(exchange='direct_logs',
  21. queue=queue_name,
  22. routing_key=severity) #exchange 接收到消息。然后把消息交给Q里,这里是指定Q,如果不指定,就丢失了消息
  23.  
  24. print(' [*] Waiting for logs. To exit press CTRL+C')
  25.  
  26. def callback(ch, method, properties, body):
  27. print(" [x] %r:%r" % (method.routing_key, body))
  28.  
  29. channel.basic_consume(callback,
  30. queue=queue_name,
  31. no_ack=True)
  32.  
  33. channel.start_consuming() #开始接收

运行:python3 rabbit-direct-recv.py aa    注释:recv端开启一个以aa为routingKey的信息

所以send开启info  recv端也必须开启info,

更细致的消息过滤(exchange type=topic)

send端

  1. import pika
  2. import sys
  3.  
  4. connection = pika.BlockingConnection(pika.ConnectionParameters(
  5. host='localhost'))
  6. channel = connection.channel()
  7.  
  8. channel.exchange_declare(exchange='topic_logs',
  9. type='topic')
  10.  
  11. routing_key = sys.argv[1] if len(sys.argv) > 1 else 'anonymous.info'
  12. message = ' '.join(sys.argv[2:]) or 'Hello World!'
  13. channel.basic_publish(exchange='topic_logs',
  14. routing_key=routing_key,
  15. body=message)
  16. print(" [x] Sent %r:%r" % (routing_key, message))
  17. connection.close()

recv端

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

RabbitMQ操作的更多相关文章

  1. 开源RabbitMQ操作组件

    开源RabbitMQ操作组件 对于目前大多的.NET项目,其实使用的技术栈都是差不多,估计现在很少用控件开发项目的了,毕竟一大堆问题.对.NET的项目,目前比较适合的架构ASP.NET MVC,ASP ...

  2. Python之RabbitMQ操作

    RabbitMQ是一个消息代理,从“生产者”接收消息并传递消息至“消费者”,期间可根据规则路由.缓存.持久化消息.“生产者”也即message发送者以下简称P,相对应的“消费者”乃message接收者 ...

  3. 简单易用的.NET免费开源RabbitMQ操作组件EasyNetQ解析

    对于目前大多的.NET项目,其实使用的技术栈都是差不多,估计现在很少用控件开发项目的了,毕竟一大堆问题.对.NET的项目,目前比较适合的架构ASP.NET MVC,ASP.NET WebAPI,ORM ...

  4. Part1.1 、RabbitMQ 操作使用

    本节目录: 一.最基本的生产者消费者二.acknowledgment 消息不丢失的方法. 三.durable 消息不丢失 (消息持久化) 四.消息获取顺序   RabbitMQ安装. (1.1).ce ...

  5. php rabbitmq操作类及生产者和消费者实例代码 转

    注意事项: 1.accept.php消费者代码需要在命令行执行 2.'username'=>'asdf','password'=>'123456' 改成自己的帐号和密码 RabbitMQC ...

  6. 使用EasyNetQ简化RabbitMQ操作

    关于具体的操作看查看官方文档:https://github.com/EasyNetQ/EasyNetQ 也可以参考中文翻译版本:http://www.cnblogs.com/HuangLiang/p/ ...

  7. RabbitMQ操作代码封装

    1.Message.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; u ...

  8. 二、RabbitMQ操作

    1.RabbitMQ发送与接收. 2.RabbitMQ发送与接收. 3.RabbitMQ发送与接收.

  9. RabbitMQ学习之(五)_一个基于PHP的RabbitMQ操作类

    //amqp.php类文件 <?php class Amqp { public $e_name; public $q_name; public $k_route; public $channel ...

随机推荐

  1. SET NOCOUNT 怎么理解

    参考文章:http://www.cnblogs.com/si812cn/archive/2008/06/11/1217113.html 我简单的理解就是: 执行sql语句时 SET NOCOUNT O ...

  2. 【.NET MF】.NET Micro Framework USB移植

    1.开发环境 windows 7  32位 MDK 4.54 .Net Micro Framework Porting Kit 4.2(RTM QFE2) .Net Micro Framework   ...

  3. alias拦截器的使用

    在SSH项目中,有时需要由一个Action跳转到另一个Action.有两种方式可以实现Action之间的跳转,一种是chain,另一种是redirectAction,这两种方式之间的区别是chain是 ...

  4. activiti工作流的web流程设计器整合视频教程 SSM和独立部署

    本视频为activiti工作流的web流程设计器整合视频教程 整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器) 本视频共讲了两种整合方式 1. 流 ...

  5. SSH框架使用注解简化代码

    注释的优势: 1.最简单直接的优势就是减少了配置文件的代码量. 2.注释和Java代码位于一个文件中,而XML 配置采用独立的配置文件.配置信息和 Java 代码放在一起,有助于增强程序的内聚性.而采 ...

  6. 如何在web中实现类似excel的表格控件

    Execl功能非常强大,内置的很多函数或公式可以大大提高对数据的加工处理能力.那么在web中有没有类似的控件呢?经过一番搜寻,发现handsontable具备了基本的excel功能支持公式,同时能对数 ...

  7. js生成一个不重复的ID的函数的进化之路

    在MongoDB中的ObjectID,可以理解为是一个不会重复的ID,这里有个链接http://blog.csdn.net/xiamizy/article/details/41521025感兴趣可以去 ...

  8. 深入理解javascript选择器API系列第一篇——4种元素选择器

    × 目录 [1]id属性 [2]标签名 [3]name属性[4]all 前面的话 说到最常见的DOM应用,恐怕就要数取得特定的某个或某组元素的引用了.DOM定义了许多方式来选取元素,包括getElem ...

  9. SecutrCRTt 连接VirtualBox 中的Ubuntu -端口转发

    端口转发: 设置>网络>端口转发   端口转发: 子系统地址通过在Linux系统总使用ifconfig查看:   还需要在linux主机上安装sshd sudo apt-get insta ...

  10. 关于addSubView需要注意的事项 -今天吃了一个大亏

    addSubview: Adds a view to the end of the receiver’s list of subviews. 译:增加一个视图到接收者的子视图列表中. - (void) ...