Exemplo n.º 1
0
    def on_message(self, channel, method, props, body):
        """ 消息处理函数, 每当接收到一个完整消息后会调用该函数

        """
        message = json.loads(body)
        msg_type = message['header']['type']            # 获取消息头部
        msg_body = message['body']                      # 获取消息体

        # 获取消息处理函数
        if msg_type in CALLBACK_MANAGER:
            _do_task = CALLBACK_MANAGER[msg_type]
        else:
            self.acknowledge_message(delivery_tag=method.delivery_tag, channel=channel)
            LOG.error('message handler %s is not implemented' % msg_type)
            return

        # 执行消息处理函数
        result = _do_task(self, msg_body)

        # 根据结果判断是否要给发送者响应
        if result is None or not props.reply_to:
            self.acknowledge_message(delivery_tag=method.delivery_tag, channel=channel)
        else:
            return_msg = dict()
            return_msg['header'] = message['header']
            return_msg['body'] = result
            self.acknowledge_message(delivery_tag=method.delivery_tag, channel=channel)
            self.send_result(channel, props, return_msg)
Exemplo n.º 2
0
 def create_host_connection(self, host_index, for_listening=False):
     """Create new connection to host #host_index
     :param host_index: Integer, number of host for connection establishing
     :param for_listening: Boolean, creates connection for listening if True
     :return: New connection
     """
     with self._connection_lock:
         host = self._host_list[host_index]
         connection_params = pika.ConnectionParameters(
             host=host,
             port=self.conf.mq_port,
             credentials=pika.credentials.PlainCredentials(self.conf.mq_username, self.conf.mq_password),
             heartbeat_interval=self._heartbeat_interval if for_listening else None,
             **self._common_pika_params
         )
         try:
             if for_listening:
                 connection = None
             else:
                 connection = pika.BlockingConnection(parameters=connection_params)
                 connection.params = connection_params
                 LOG.info('connected rabbitmq-server %s:%s' % (host, self.conf.mq_port))
             return connection
         except:
             LOG.error(traceback.format_exc())
Exemplo n.º 3
0
 def create_host_connection(self, host_index, for_listening=False):
     """Create new connection to host #host_index
     :param host_index: Integer, number of host for connection establishing
     :param for_listening: Boolean, creates connection for listening if True
     :return: New connection
     """
     with self._connection_lock:
         host = self._host_list[host_index]
         connection_params = pika.ConnectionParameters(
             host=host,
             port=self.conf.mq_port,
             credentials=pika.credentials.PlainCredentials(
                 self.conf.mq_username, self.conf.mq_password),
             heartbeat_interval=self._heartbeat_interval
             if for_listening else None,
             **self._common_pika_params)
         try:
             if for_listening:
                 connection = None
             else:
                 connection = pika.BlockingConnection(
                     parameters=connection_params)
                 connection.params = connection_params
                 LOG.info('connected rabbitmq-server %s:%s' %
                          (host, self.conf.mq_port))
             return connection
         except:
             LOG.error(traceback.format_exc())
Exemplo n.º 4
0
    def on_channel_closed(self, channel, reply_code, reply_text):
        """ 连接通道关闭响应函数, 在这里我们仅仅做了关闭连接

        """
        LOG.warning('Channel was closed: (%s) %s' % (reply_code, reply_text))
        if not self._closing:
            self._connection.close()
Exemplo n.º 5
0
    def close_connection(self):
        """ 主动关闭连接

        """
        LOG.info('Closing connection')
        self._closing = True
        self._connection.close()
Exemplo n.º 6
0
    def close_channel(self):
        """ 主动关闭连接通道,发送Channel.Close命令给RabbitMQ

        """
        LOG.info('Closing the channel')
        if self._channel:
            self._channel.close()
Exemplo n.º 7
0
    def on_rpc_consumer_cancelled(self, method_frame):
        """ 注销消费者响应函数

        """
        LOG.info('Consumer was cancelled remotely, shutting down: %r' % method_frame)
        if self._channel:
            # self._channel.close()
            pass
Exemplo n.º 8
0
    def start_rpc_consuming(self):
        """ 准备消费消息

        """
        LOG.info('Starting to receive response message...')
        self.add_on_rpc_cancel_callback()

        # 注册回调队列消息响应函数
        self._consumer_tag = self._channel.basic_consume(self.on_message, self.reply_queue)
Exemplo n.º 9
0
    def on_connection_closed(self, connection, reply_code, reply_text):
        """ 连接关闭响应函数

        """
        self._channel = None
        if self._closing:
            self._connection.ioloop.stop()
        else:
            LOG.warning('Connection closed, reopening in 5 seconds: (%s) %s' % (reply_code, reply_text))
            self._connection.add_timeout(5, self.reconnect)
Exemplo n.º 10
0
    def on_delivery_confirmation(self, method_frame):
        """ 当收到Basic.ACK命令时, 该函数被调用; RabbitMQ响应Basic.Publish命令

        """
        confirmation_type = method_frame.method.NAME.split('.')[1].lower()
        LOG.info('Received %s for delivery tag: %i' % (confirmation_type, method_frame.method.delivery_tag))
        if confirmation_type == 'ack':
            self._acked += 1
        elif confirmation_type == 'nack':
            self._nacked += 1
        self._deliveries.remove(method_frame.method.delivery_tag)
Exemplo n.º 11
0
    def on_queue_declared(self, method_frame):
        """ 队列创建完成响应函数,接收RabbitMQ发送过来的Queue.DeclareOk命令

        """
        binding_key = None
        if self.reply_queue is not None:
            binding_key = '#.%s.#' % self.reply_queue
        LOG.info('Binding %s to %s with %s' % (self.exchange, self.reply_queue, binding_key))

        # 绑定队列和交换机
        self._channel.queue_bind(self.on_rpc_bindok, self.reply_queue, self.exchange, binding_key)
Exemplo n.º 12
0
    def stop(self):
        """ 主动注销消费者并关闭连接,当RabbitMQ确认注销消费者后,on_cancelok函数
            将会被调用,在这个函数里关闭连接通道和连接

        """
        LOG.info('Stopping')
        self._stopping = True
        self.close_channel()
        self.close_connection()
        self._connection.ioloop.start()
        LOG.info('Stopped')
Exemplo n.º 13
0
    def send_message(self, message, queue=None, reply_queue=None):
        """ 阻塞发送消息,等待返回结果
        :param message: messageclient.Message, 消息对象
        :param queue: str, 发送队列名称
        :param reply_queue: str, 响应结果队列名称
        :return: dict, 消息响应结果

        """
        self.lock.acquire()         # 获取锁访问self.reply_queue

        if queue is None:
            return
        routing_key = queue         # 将消息发送给指定的队列

        if reply_queue is None:
            reply_queue = 'reply-%s' % str(uuid.uuid4())

        if self._stopping:
            return

        # 循环等待通道处于打开状态
        while not (self._channel and self._channel.is_open):
            time.sleep(0.02)

        # 创建回调队列,注册回调队列响应函数以及消费队列
        self._consumer_tag = self.declare_queue(reply_queue, exclusive=False, auto_delete=True, durable=False)

        self.reply_response = None
        self.correlation_id = str(uuid.uuid4())
        properties = pika.BasicProperties(app_id=None,
                                          reply_to=reply_queue,
                                          correlation_id=self.correlation_id,
                                          content_type='application/json',
                                          headers=None)
        # 发送消息
        self._channel.basic_publish(self.exchange,
                                    routing_key,
                                    json.dumps(message.data, ensure_ascii=False),
                                    properties)
        self._message_number += 1
        self._deliveries.append(self._message_number)
        LOG.info('publiser send message # %i' % self._message_number)

        # 等待消息响应结果
        while self.reply_response is None:
            time.sleep(0.02)
        result = self.reply_response

        # self._channel.basic_cancel(consumer_tag=self._consumer_tag, nowait=True)
        self.lock.release()  # 释放锁唤醒其他等待线程访问
        return result
Exemplo n.º 14
0
    def _decorator(fn):
        if not util.is_callable(fn):
            LOG.error('function %s is not callable' % fn)
            sys.exit(-1)

        def __decorator(self, message):
            result = fn(self, message)
            return result

        # 将被装饰的用户定义的函数注册到
        if type is not None and not type in CALLBACK_MANAGER:
            CALLBACK_MANAGER[type] = __decorator

        return __decorator
Exemplo n.º 15
0
    def connect(self):
        """ 连接RabbitMQ, 返回连接句柄. 当连接建立后,on_connection_open方法将会被调用

        """
        LOG.info('Connecting to RabbitMQ %s' % self.conf.mq_hosts)
        connection_params = pika.ConnectionParameters(
            host=self.conf.mq_hosts,
            port=self.conf.mq_port,
            credentials=pika.credentials.PlainCredentials(self.conf.mq_username, self.conf.mq_password)
        )
        return pika.SelectConnection(parameters=connection_params,
                                     on_open_callback=self.on_connection_open,
                                     on_open_error_callback=None,
                                     on_close_callback=None,
                                     stop_ioloop_on_close=False)
Exemplo n.º 16
0
    def declare_queue(self, queue_name, exclusive=False, auto_delete=False, durable=True):
        """ 创建队列,向RabbitMQ发送Queue.Declare命令

        """
        LOG.info('Declaring queue %s' % queue_name)

        self.reply_queue = queue_name
        if durable:
            self.reply_queues.add(queue_name)

        while not self._channel.is_open:
            time.sleep(0.02)

        # 创建回调队列
        consumer_tag = self._channel.queue_declare(self.on_queue_declared, queue_name, durable=durable,
                                                   exclusive=exclusive, auto_delete=auto_delete)

        return consumer_tag
Exemplo n.º 17
0
    def send_request(self, message, queue=None, reply_queue=None):
        """ 异步发送消息
        :param queue: str, 队列名称
        :param reply_queue: str, 响应队列名称
        :return: None

        """
        if queue is None:
            return
        routing_key = queue  # 将消息发送给指定的队列

        if self._stopping:
            return

        # 循环等待通道处于打开状态
        while not (self._channel and self._channel.is_open):
            time.sleep(0.02)

        if reply_queue is None:
            reply_queue = ''
        else:
            # self.declare_queue(reply_queue)     # 创建回调队列
            # self._channel.queue_declare(None, reply_queue, nowait=True, durable=True)
            # binding_key = '#.%s.#' % reply_queue
            # self._channel.queue_bind(None, reply_queue, self.exchange, binding_key, nowait=True)
            pass

        self.response = None
        self.correlation_id = str(uuid.uuid4())
        properties = pika.BasicProperties(app_id=None,
                                          reply_to=reply_queue,
                                          correlation_id=self.correlation_id,
                                          content_type='application/json',
                                          headers=None)
        # 发送消息
        self._channel.basic_publish(self.exchange,
                                    routing_key,
                                    json.dumps(message.data, ensure_ascii=False),
                                    properties)
        self._message_number += 1
        self._deliveries.append(self._message_number)
        LOG.info('publiser send request # %i' % self._message_number)
Exemplo n.º 18
0
    def broadcast_message(self, message, queues=[]):
        """ 广播消息

        """
        routing_key = None
        if queues:
            routing_key = '.'.join(queues)

        if self._stopping:
            return

        while not (self._channel and self._channel.is_open):
            time.sleep(0.02)

        properties = pika.BasicProperties(app_id=None, content_type='application/json', headers=None)
        self._channel.basic_publish(self.exchange,
                                    routing_key,
                                    json.dumps(message.data, ensure_ascii=False),
                                    properties)

        self._message_number += 1
        self._deliveries.append(self._message_number)
        LOG.info('broadcast message # %i' % self._message_number)
Exemplo n.º 19
0
    def publish_message(self, message, queue=None):
        """ 发送消息到queue指定队列
        :param message: messageclient.Message, 消息对象
        :param queue: str, 消息的路由关键字,匹配binding_key
        :return:

        """
        routing_key = queue

        if self._stopping:
            return

        while not (self._channel and self._channel.is_open):
            time.sleep(0.02)

        properties = pika.BasicProperties(app_id=None, content_type='application/json', headers=None)
        self._channel.basic_publish(self.exchange,
                                    routing_key,
                                    json.dumps(message.data, ensure_ascii=False),
                                    properties)
        self._message_number += 1
        self._deliveries.append(self._message_number)
        LOG.info('Published message # %i' % self._message_number)
Exemplo n.º 20
0
    def open_channel(self):
        """ 建立连接通道,给RabbitMQ发送Channel.Open命令,当接收到Channel.Open.OK时表示通道已建立

        """
        LOG.info('Creating a new channel to RabbitMQ.')
        self._connection.channel(on_open_callback=self.on_channel_open)
Exemplo n.º 21
0
    def setup_exchange(self, exchange_name):
        """ 创建交换机,向RabbitMQ发送Exchange.Declare命令

        """
        LOG.info('Declaring exchange %s' % exchange_name)
        self._channel.exchange_declare(self.on_exchange_declareok, exchange_name, self.exchange_type, durable=True)