Kombu 基础
来源:互联网 发布:linux服务器禁端口扫描 编辑:程序博客网 时间:2024/06/01 09:14
本文地址:http://blog.csdn.net/spch2008/article/details/11530007
AMQP协议:
Producer产生消息,将消息赋予路由信息,发送给exchange。
queue存储消息,并将消息发送Consumer
bindings queues与exchange通过路由信息进行绑定。发送过来的消息带有路由信息,exchange提取路由信息和queues与exchange绑定的路由信息匹配,
匹配成功后,将消息发给相应队列。
consumer 从queues中提取信息,并消耗。
exchange 接收消息,并路由到相应队列。
Kombu代码示例:
producer.py
#!/usr/bin/pythonfrom kombu.entity import Exchangefrom kombu.messaging import Producerfrom kombu.connection import Connectionconnection = Connection('amqp://guest:bupt@172.16.4.1:5672//')channel = connection.channel()media_exchange = Exchange('media', 'direct', channel)producer = Producer(channel, exchange=media_exchange, routing_key='video')producer.publish({'name': '/tmp/lolcat1.avi', 'size': 1301013})思路很简单:
1. 创建连接
2. 获得一个channel
3. 创建一个exchange,名字为‘media’,类型为‘direct’。
4. 创建一个Producer,指定exchange与routing_key,这样,发送信息的时候填充路由信息,发送到指定exchange。也可以在publish的时候指定。
5. 发送消息。
consumer.py
#!/usr/bin/pythonfrom kombu.entity import Exchange, Queuefrom kombu.messaging import Consumerfrom kombu.connection import Connectiondef process_media(body, message): print body message.ack()connection = Connection('amqp://guest:bupt@172.16.4.1:5672//')channel = connection.channel()media_exchange = Exchange('media', 'direct', channel)video_queue = Queue('video', exchange=media_exchange, routing_key='video', channel=channel)consumer = Consumer(channel, queues=[video_queue], callbacks=[process_media]) consumer.consume()while True: connection.drain_events()consumer.cancel()
思路很明确:
1. 创建连接
2. 获得channel
3. 创建exchange
4. 创建队列并与exchange绑定
5. 创建Consumer
6. consume() 向server注册,表明现在可以接收信息啦。server可以向该consumer发送消息。
7. drain_events阻塞程序,等待消息到来。当消息到来时,会执行回调函数process_media
8. cancel()通知server不要向该consumer发送任何消息啦。
疑惑:
1. channel是什么
When producers and consumers connects to the broker using a TCP socket after authenticating the connection they establish a channel where AMQP commands are sent. The channel is a virtual path inside a TCP connection between this is very useful because there can be multiple channels inside the TCP connection each channels is identified using an unique ID.
2. process_media的参数message是什么?为什么要调用message.ack()?
打印message,输出kombu.transport.pyamqplib.Message object at 0x28d2b90。于是定位到Message类。
class Message(base.Message): """A message received by the broker. .. attribute:: body The message body. .. attribute:: channel The channel instance the message was received on. """ def __init__(self, channel, msg, **kwargs): props = msg.properties super(Message, self).__init__(channel, body=msg.body, delivery_tag=msg.delivery_tag, content_type=props.get("content_type"), content_encoding=props.get("content_encoding"), delivery_info=msg.delivery_info, properties=msg.properties, headers=props.get("application_headers"), **kwargs)可以通过message取得想要的信息。其次,为什么要调用ack呢?
如果队列要求回复确认信息,那么只有当用户返回一个确认信息,表明该message已经收到,message才会从队列中消失,否则,message一直存放在队列中。
3. drain_events做了些什么?
kombu.transport.pyamqlib.Connection.drain_events
def drain_events(self, allowed_methods=None, timeout=None): """Wait for an event on any channel.""" return self.wait_multi(self.channels.values(), timeout=timeout)def wait_multi(self, channels, allowed_methods=None, timeout=None):"""Wait for an event on a channel."""chanmap = dict((chan.channel_id, chan) for chan in channels)chanid, method_sig, args, content = self._wait_multiple(chanmap.keys(), allowed_methods, timeout=timeout)channel = chanmap[chanid]amqp_method = self._method_override.get(method_sig) or \channel._METHOD_MAP.get(method_sig, None)return amqp_method(channel, args)amqp_method即为回调函数。
ampqlib.client_0_8.channel.py.Channel.
_METHOD_MAP = { (60, 60): _basic_deliver, (60, 71): _basic_get_ok, }根据method_sig取得相应函数
def _basic_deliver(self, args, msg): consumer_tag = args.read_shortstr() func = self.callbacks.get(consumer_tag, None) if func is not None: func(msg)从channel中的callback中获得用户注册的回调函数。明明在创建consumer的时候注册的回调函数,为什么回调函数会在channel中呢?
Comsumer类的comsume函数:
def consume(self, no_ack=None): self._basic_consume(T, no_ack=no_ack, nowait=False)def _basic_consume(self, queue, consumer_tag=None, no_ack=no_ack, nowait=True): queue.consume(tag, self._receive_callback, no_ack=no_ack, nowait=nowait)def _receive_callback(self, message): self.receive(decoded, message) def receive(self, body, message): callbacks = self.callbacks if not callbacks: raise NotImplementedError("Consumer does not have any callback") [callback(body, message) for callback in callbacks]注册的回调函数被包装了一下。新的回调函数传入了queue.consume
def consume(self, consumer_tag='', callback=None, no_ack=None, nowait=False): return self.channel.basic_consume(queue=self.name, no_ack=no_ack, consumer_tag=consumer_tag or '', callback=callback, nowait=nowait)回调函数进入channel中。
总结一下:drain_events等待队列中的消息,当取得消息后,会调用回调函数进行相应处理。
4. 从connection获得Producer与Consumer
有一个简便方法,可以直接从connection中获得Producer或者Consumer。
consumer = connection.Consumer(queues=[video_queue], callbacks=[process_media])
完……
- Kombu 基础
- Kombu 基础
- OpenStack基础之Kombu
- OpenStack基础组件kombu杂谈
- kombu websites
- Kombu Exchange
- Kombu Queue
- Kombu Consumer
- Kombu socked closed
- nova oslo.messageing kombu
- Kombu小练习
- kombu消息框架<一>
- kombu消息框架<二>
- AMQP,RabbitMQ,Qpidd和Kombu
- kombu------python的消息库
- openstack nova 基础知识——Kombu
- openstack nova 基础知识——Kombu
- openstack nova 基础知识——Kombu
- oracle ceil和floor函数
- GPRS 中的PDP上下文名词解释
- 如何在github中贡献自己的力量
- HDU1150-Machine Schedule
- 给定一个字符串,输出其所有的可能排列
- Kombu 基础
- Visual Assist X Options(VAssistX)如何修改倾斜
- kermit代替minicom
- 双线性插值算法
- 网页中嵌入swf文件的几种方法
- 目标跟踪理论方法小结 .
- 数据库 创建数据库 ,表,表中插入数据,以及表、无用字段的删除。
- JAVA中super和this的区别和用法
- Git使用入门