예제 #1
0
    def send_request(self, multipart_message):

        envelope = multipart_message[zmq_names.MULTIPART_IDX_ENVELOPE]

        LOG.info(_LI("Envelope: %s") % envelope)

        target = envelope[zmq_names.FIELD_TARGET]
        dealer_socket, hosts = self._check_hosts_connections(target)

        if not dealer_socket.connections:
            # NOTE(ozamiatin): Here we can provide
            # a queue for keeping messages to send them later
            # when some listener appears. However such approach
            # being more reliable will consume additional memory.
            LOG.warning(
                _LW("Request %s was dropped because no connection") %
                envelope[zmq_names.FIELD_MSG_TYPE])
            return

        self.reply_receiver.track_socket(dealer_socket.handle)

        LOG.info(
            _LI("Sending message %(message)s to a target %(target)s") % {
                "message": envelope[zmq_names.FIELD_MSG_ID],
                "target": envelope[zmq_names.FIELD_TARGET]
            })

        if envelope[zmq_names.FIELD_MSG_TYPE] in zmq_names.MULTISEND_TYPES:
            for _ in range(dealer_socket.connections_count()):
                self._send_request(dealer_socket, multipart_message)
        else:
            self._send_request(dealer_socket, multipart_message)
예제 #2
0
    def __init__(self, conf, context, matchmaker):
        self.conf = conf
        self.context = context
        super(UniversalQueueProxy, self).__init__()
        self.matchmaker = matchmaker
        self.poller = zmq_async.get_poller(zmq_concurrency='native')

        self.fe_router_socket = zmq_socket.ZmqRandomPortSocket(
            conf, context, zmq.ROUTER)
        self.be_router_socket = zmq_socket.ZmqRandomPortSocket(
            conf, context, zmq.ROUTER)

        self.poller.register(self.fe_router_socket.handle,
                             self._receive_in_request)
        self.poller.register(self.be_router_socket.handle,
                             self._receive_in_request)

        self.fe_router_address = zmq_address.combine_address(
            self.conf.rpc_zmq_host, self.fe_router_socket.port)
        self.be_router_address = zmq_address.combine_address(
            self.conf.rpc_zmq_host, self.fe_router_socket.port)

        self.pub_publisher = zmq_pub_publisher.PubPublisherProxy(
            conf, matchmaker)

        self.matchmaker.register_publisher(
            (self.pub_publisher.host, self.fe_router_address))
        LOG.info(_LI("[PUB:%(pub)s, ROUTER:%(router)s] Run PUB publisher"),
                 {"pub": self.pub_publisher.host,
                  "router": self.fe_router_address})
        self.matchmaker.register_router(self.be_router_address)
        LOG.info(_LI("[Backend ROUTER:%(router)s] Run ROUTER"),
                 {"router": self.be_router_address})
    def send_request(self, multipart_message):

        envelope = multipart_message[zmq_names.MULTIPART_IDX_ENVELOPE]

        LOG.info(_LI("Envelope: %s") % envelope)

        target = envelope[zmq_names.FIELD_TARGET]
        dealer_socket, hosts = self._check_hosts_connections(target)

        if not dealer_socket.connections:
            # NOTE(ozamiatin): Here we can provide
            # a queue for keeping messages to send them later
            # when some listener appears. However such approach
            # being more reliable will consume additional memory.
            LOG.warning(_LW("Request %s was dropped because no connection")
                        % envelope[zmq_names.FIELD_MSG_TYPE])
            return

        self.reply_receiver.track_socket(dealer_socket.handle)

        LOG.info(_LI("Sending message %(message)s to a target %(target)s")
                 % {"message": envelope[zmq_names.FIELD_MSG_ID],
                    "target": envelope[zmq_names.FIELD_TARGET]})

        if envelope[zmq_names.FIELD_MSG_TYPE] in zmq_names.MULTISEND_TYPES:
            for _ in range(dealer_socket.connections_count()):
                self._send_request(dealer_socket, multipart_message)
        else:
            self._send_request(dealer_socket, multipart_message)
예제 #4
0
    def _redirect_reply(self, reply):
        LOG.info(_LI("Reply proxy %s") % reply)
        if reply[zmq_names.IDX_REPLY_TYPE] == zmq_names.ACK_TYPE:
            LOG.info(_LI("Acknowledge dropped %s") % reply)
            return

        LOG.info(_LI("<- Redirecting reply to ROUTER: reply: %s")
                 % reply[zmq_names.IDX_REPLY_BODY:])

        self.router_socket.send_multipart(reply[zmq_names.IDX_REPLY_BODY:])
    def __init__(self, conf, context, matchmaker):
        super(RouterProxy, self).__init__(conf, context, matchmaker)
        LOG.info(_LI("Polling at ROUTER proxy"))

        self.dealer_publisher \
            = zmq_dealer_publisher_proxy.DealerPublisherProxy(
                conf, matchmaker, self.poller)

        self.matchmaker.register_router(self.router_address)
        LOG.info(_LI("ROUTER:%(router)s] Run ROUTER publisher"),
                 {"router": self.router_address})
 def _update_records(self):
     self.matchmaker.register_publisher(
         (self.publisher_address, self.fe_router_address),
         expire=self.conf.zmq_target_expire)
     LOG.info(_LI("[PUB:%(pub)s, ROUTER:%(router)s] Update PUB publisher"),
              {"pub": self.publisher_address,
               "router": self.fe_router_address})
     self.matchmaker.register_router(self.be_router_address,
                                     expire=self.conf.zmq_target_expire)
     LOG.info(_LI("[Backend ROUTER:%(router)s] Update ROUTER"),
              {"router": self.be_router_address})
    def __init__(self, conf, context, matchmaker):
        super(RouterProxy, self).__init__(conf, context, matchmaker)
        LOG.info(_LI("Polling at ROUTER proxy"))

        self.dealer_publisher \
            = zmq_dealer_publisher_proxy.DealerPublisherProxy(
                conf, matchmaker, self.poller)

        self.matchmaker.register_router(self.router_address)
        LOG.info(_LI("ROUTER:%(router)s] Run ROUTER publisher"),
                 {"router": self.router_address})
    def __init__(self, conf, context, matchmaker):
        super(PublisherProxy, self).__init__(conf, context, matchmaker)
        LOG.info(_LI("Polling at PUBLISHER proxy"))

        self.pub_publisher = zmq_pub_publisher.PubPublisherProxy(
            conf, matchmaker)

        self.matchmaker.register_publisher(
            (self.pub_publisher.host, self.router_address))
        LOG.info(_LI("[PUB:%(pub)s, ROUTER:%(router)s] Run PUB publisher"),
                 {"pub": self.pub_publisher.host,
                  "router": self.router_address})
예제 #9
0
    def __init__(self, conf, context, matchmaker):
        super(PublisherProxy, self).__init__(conf, context, matchmaker)
        LOG.info(_LI("Polling at PUBLISHER proxy"))

        self.pub_publisher = zmq_pub_publisher.PubPublisherProxy(
            conf, matchmaker)

        self.matchmaker.register_publisher(
            (self.pub_publisher.host, self.router_address))
        LOG.info(_LI("[PUB:%(pub)s, ROUTER:%(router)s] Run PUB publisher"),
                 {"pub": self.pub_publisher.host,
                  "router": self.router_address})
예제 #10
0
    def reply(self, reply=None, failure=None, log_failure=True):
        if not self.msg_id:
            # NOTE(Alexei_987) not sending reply, if msg_id is empty
            #    because reply should not be expected by caller side
            return

        # NOTE(sileht): return without using a connection if possible
        if (self.reply_q and
            not self._obsolete_reply_queues.reply_q_valid(self.reply_q,
                                                          self.msg_id)):
            return

        # NOTE(sileht): we read the configuration value from the driver
        # to be able to backport this change in previous version that
        # still have the qpid driver
        duration = self.listener.driver.missing_destination_retry_timeout
        timer = rpc_common.DecayingTimer(duration=duration)
        timer.start()

        first_reply_sent = False
        while True:
            try:
                with self.listener.driver._get_connection(
                        rpc_common.PURPOSE_SEND) as conn:
                    if self.listener.driver.send_single_reply:
                        self._send_reply(conn, reply, failure,
                                         log_failure=log_failure,
                                         ending=True)
                    else:
                        if not first_reply_sent:
                            self._send_reply(conn, reply, failure,
                                             log_failure=log_failure)
                            first_reply_sent = True
                        self._send_reply(conn, ending=True)
                return
            except rpc_amqp.AMQPDestinationNotFound:
                if timer.check_return() > 0:
                    LOG.info(_LI("The reply %(msg_id)s cannot be sent  "
                                 "%(reply_q)s reply queue don't exist, "
                                 "retrying...") % {
                                     'msg_id': self.msg_id,
                                     'reply_q': self.reply_q})
                    time.sleep(0.25)
                else:
                    self._obsolete_reply_queues.add(self.reply_q, self.msg_id)
                    LOG.info(_LI("The reply %(msg_id)s cannot be sent  "
                                 "%(reply_q)s reply queue don't exist after "
                                 "%(duration)s sec abandoning...") % {
                                     'msg_id': self.msg_id,
                                     'reply_q': self.reply_q,
                                     'duration': duration})
                    return
예제 #11
0
 def _update_records(self):
     self.matchmaker.register_publisher(
         (self.publisher_address, self.fe_router_address),
         expire=self.conf.zmq_target_expire)
     LOG.info(_LI("[PUB:%(pub)s, ROUTER:%(router)s] Update PUB publisher"),
              {
                  "pub": self.publisher_address,
                  "router": self.fe_router_address
              })
     self.matchmaker.register_router(self.be_router_address,
                                     expire=self.conf.zmq_target_expire)
     LOG.info(_LI("[Backend ROUTER:%(router)s] Update ROUTER"),
              {"router": self.be_router_address})
예제 #12
0
 def __init__(self, conf, context, queue, matchmaker):
     super(OutgoingQueueProxy, self).__init__(conf, context)
     self.queue = queue
     self.matchmaker = matchmaker
     self.publisher = zmq_dealer_publisher.DealerPublisher(
         conf, matchmaker)
     LOG.info(_LI("Polling at outgoing proxy ..."))
예제 #13
0
    def register(self, proxy, in_addr, zmq_type_in,
                 in_bind=True, subscribe=None):

        LOG.info(_LI("Registering reactor"))

        if zmq_type_in not in (zmq.PULL, zmq.SUB):
            raise RPCException("Bad input socktype")

        # Items push in.
        inq = ZmqSocket(in_addr, zmq_type_in, bind=in_bind,
                        subscribe=subscribe)

        self.proxies[inq] = proxy
        self.sockets.append(inq)

        LOG.info(_LI("In reactor registered"))
예제 #14
0
    def create_consumer(self, topic, proxy, fanout=False):
        # Register with matchmaker.
        _get_matchmaker().register(topic, CONF.rpc_zmq_host)

        # Subscription scenarios
        if fanout:
            sock_type = zmq.SUB
            subscribe = ('', fanout)[type(fanout) == str]
            topic = 'fanout~' + topic.split('.', 1)[0]
        else:
            sock_type = zmq.PULL
            subscribe = None
            topic = '.'.join((topic.split('.', 1)[0], CONF.rpc_zmq_host))

        if topic in self.topics:
            LOG.info(_LI("Skipping topic registration. Already registered."))
            return

        # Receive messages from (local) proxy
        inaddr = "ipc://%s/zmq_topic_%s" % \
            (CONF.rpc_zmq_ipc_dir, topic)

        LOG.debug("Consumer is a zmq.%s", ['PULL',
                                           'SUB'][sock_type == zmq.SUB])

        self.reactor.register(proxy,
                              inaddr,
                              sock_type,
                              subscribe=subscribe,
                              in_bind=False)
        self.topics.append(topic)
예제 #15
0
            def publisher(waiter):
                LOG.info(_LI("Creating proxy for topic: %s"), topic)

                try:
                    # The topic is received over the network,
                    # don't trust this input.
                    if self.badchars.search(topic) is not None:
                        emsg = _("Topic contained dangerous characters.")
                        LOG.warn(emsg)
                        raise RPCException(emsg)

                    out_sock = ZmqSocket("ipc://%s/zmq_topic_%s" %
                                         (ipc_dir, topic),
                                         sock_type, bind=True)
                except RPCException:
                    waiter.send_exception(*sys.exc_info())
                    return

                self.topic_proxy[topic] = eventlet.queue.LightQueue(
                    CONF.rpc_zmq_topic_backlog)
                self.sockets.append(out_sock)

                # It takes some time for a pub socket to open,
                # before we can have any faith in doing a send() to it.
                if sock_type == zmq.PUB:
                    eventlet.sleep(.5)

                waiter.send(True)

                while(True):
                    data = self.topic_proxy[topic].get()
                    out_sock.send(data, copy=False)
예제 #16
0
            def publisher(waiter):
                LOG.info(_LI("Creating proxy for topic: %s"), topic)

                try:
                    # The topic is received over the network,
                    # don't trust this input.
                    if self.badchars.search(topic) is not None:
                        emsg = _("Topic contained dangerous characters.")
                        LOG.warn(emsg)
                        raise RPCException(emsg)

                    out_sock = ZmqSocket("ipc://%s/zmq_topic_%s" %
                                         (ipc_dir, topic),
                                         sock_type,
                                         bind=True)
                except RPCException:
                    waiter.send_exception(*sys.exc_info())
                    return

                self.topic_proxy[topic] = eventlet.queue.LightQueue(
                    CONF.rpc_zmq_topic_backlog)
                self.sockets.append(out_sock)

                # It takes some time for a pub socket to open,
                # before we can have any faith in doing a send() to it.
                if sock_type == zmq.PUB:
                    eventlet.sleep(.5)

                waiter.send(True)

                while (True):
                    data = self.topic_proxy[topic].get()
                    out_sock.send(data, copy=False)
예제 #17
0
    def create_consumer(self, topic, proxy, fanout=False):
        # Register with matchmaker.
        _get_matchmaker().register(topic, CONF.rpc_zmq_host)

        # Subscription scenarios
        if fanout:
            sock_type = zmq.SUB
            subscribe = ('', fanout)[type(fanout) == str]
            topic = 'fanout~' + topic.split('.', 1)[0]
        else:
            sock_type = zmq.PULL
            subscribe = None
            topic = '.'.join((topic.split('.', 1)[0], CONF.rpc_zmq_host))

        if topic in self.topics:
            LOG.info(_LI("Skipping topic registration. Already registered."))
            return

        # Receive messages from (local) proxy
        inaddr = "ipc://%s/zmq_topic_%s" % \
            (CONF.rpc_zmq_ipc_dir, topic)

        LOG.debug("Consumer is a zmq.%s",
                  ['PULL', 'SUB'][sock_type == zmq.SUB])

        self.reactor.register(proxy, inaddr, sock_type,
                              subscribe=subscribe, in_bind=False)
        self.topics.append(topic)
 def __init__(self, conf, poller, server):
     super(RouterConsumer, self).__init__(conf, poller, server, zmq.ROUTER)
     self.matchmaker = server.matchmaker
     self.targets = []
     self.host = zmq_address.combine_address(self.conf.rpc_zmq_host,
                                             self.port)
     LOG.info(_LI("[%s] Run ROUTER consumer"), self.host)
예제 #19
0
    def __init__(self, driver, conf, matchmaker, target, poller=None):
        super(ZmqServer, self).__init__()
        self.driver = driver
        self.conf = conf
        self.matchmaker = matchmaker
        self.target = target
        self.poller = poller or zmq_async.get_poller()

        LOG.info(
            _LI('[%(host)s] Run server %(target)s'), {
                'host': self.conf.oslo_messaging_zmq.rpc_zmq_host,
                'target': self.target
            })

        self.router_consumer = zmq_router_consumer.RouterConsumer(
            conf, self.poller, self) \
            if not conf.oslo_messaging_zmq.use_router_proxy else None
        self.dealer_consumer = zmq_dealer_consumer.DealerConsumer(
            conf, self.poller, self) \
            if conf.oslo_messaging_zmq.use_router_proxy else None
        self.sub_consumer = zmq_sub_consumer.SubConsumer(
            conf, self.poller, self) \
            if conf.oslo_messaging_zmq.use_pub_sub else None

        self.consumers = []
        if self.router_consumer is not None:
            self.consumers.append(self.router_consumer)
        if self.dealer_consumer is not None:
            self.consumers.append(self.dealer_consumer)
        if self.sub_consumer is not None:
            self.consumers.append(self.sub_consumer)
예제 #20
0
    def receive_message(self, socket):
        try:
            reply_id = socket.recv()
            empty = socket.recv()
            assert empty == b'', 'Bad format: empty delimiter expected'
            request = socket.recv_pyobj()

            LOG.info(
                _LI("Received %(msg_type)s message %(msg)s") % {
                    "msg_type": request.msg_type,
                    "msg": str(request.message)
                })

            if request.msg_type == zmq_names.CALL_TYPE:
                return zmq_incoming_message.ZmqIncomingRequest(
                    self.server, request.context, request.message, socket,
                    reply_id, self.poller)
            elif request.msg_type in zmq_names.NON_BLOCKING_TYPES:
                return RouterIncomingMessage(self.server, request.context,
                                             request.message, socket, reply_id,
                                             request.message_id, self.poller)
            else:
                LOG.error(_LE("Unknown message type: %s") % request.msg_type)

        except zmq.ZMQError as e:
            LOG.error(_LE("Receiving message failed: %s") % str(e))
예제 #21
0
파일: base.py 프로젝트: anychain/zen-common
    def get_single_host(self, target):
        """Get a single host by target.

       :param target: the target for messages
       :type target: Target
       :returns: a "hostname:port" host
       """

        hosts = self.get_hosts(target)
        if not hosts:
            err_msg = "No hosts were found for target %s." % target
            LOG.error(err_msg)
            raise oslo_messaging.InvalidTarget(err_msg, target)

        if len(hosts) == 1:
            host = hosts[0]
            LOG.info(
                _LI("A single host %(host)s found for target %(target)s.") % {
                    "host": host,
                    "target": target
                })
        else:
            host = random.choice(hosts)
            LOG.warning(
                _LW("Multiple hosts %(hosts)s were found for target "
                    " %(target)s. Using the random one - %(host)s.") % {
                        "hosts": hosts,
                        "target": target,
                        "host": host
                    })
        return host
예제 #22
0
 def connect_to_address(self, address):
     if address in self.connections:
         return
     stype = zmq_names.socket_type_str(self.socket_type)
     sid = self.handle.identity
     try:
         LOG.info(_LI("Connecting %(stype)s socket %(sid)s to %(address)s"),
                  {
                      "stype": stype,
                      "sid": sid,
                      "address": address
                  })
         self.connect(address)
     except zmq.ZMQError as e:
         LOG.error(
             _LE("Failed connecting %(stype)s-%(sid)s to "
                 "%(address)s: %(e)s"), {
                     "stype": stype,
                     "sid": sid,
                     "address": address,
                     "e": e
                 })
         raise rpc_common.RPCException(
             "Failed connecting %(stype)s-%(sid)s to %(address)s: %(e)s" % {
                 "stype": stype,
                 "sid": sid,
                 "address": address,
                 "e": e
             })
예제 #23
0
    def direct_send(self, msg_id, msg):
        """Send a 'direct' message."""

        timer = rpc_common.DecayingTimer(duration=60)
        timer.start()
        # NOTE(sileht): retry at least 60sec, after we have a good change
        # that the caller is really dead too...

        while True:
            try:
                self.publisher_send(DirectPublisher, msg_id, msg)
            except self.connection.channel_errors as exc:
                # NOTE(noelbk/sileht):
                # If rabbit dies, the consumer can be disconnected before the
                # publisher sends, and if the consumer hasn't declared the
                # queue, the publisher's will send a message to an exchange
                # that's not bound to a queue, and the message wll be lost.
                # So we set passive=True to the publisher exchange and catch
                # the 404 kombu ChannelError and retry until the exchange
                # appears
                if exc.code == 404 and timer.check_return() > 0:
                    LOG.info(
                        _LI("The exchange to reply to %s doesn't "
                            "exist yet, retrying...") % msg_id)
                    time.sleep(1)
                    continue
                raise
            return
예제 #24
0
    def _heartbeat_thread_job(self):
        """Thread that maintains inactive connections
        """
        while not self._heartbeat_exit_event.is_set():
            with self._connection_lock.for_heartbeat():

                recoverable_errors = (
                    self.connection.recoverable_channel_errors +
                    self.connection.recoverable_connection_errors)

                try:
                    try:
                        self._heartbeat_check()
                        # NOTE(sileht): We need to drain event to receive
                        # heartbeat from the broker but don't hold the
                        # connection too much times. In amqpdriver a connection
                        # is used exclusivly for read or for write, so we have
                        # to do this for connection used for write drain_events
                        # already do that for other connection
                        try:
                            self.connection.drain_events(timeout=0.001)
                        except socket.timeout:
                            pass
                    except recoverable_errors as exc:
                        LOG.info(_LI("A recoverable connection/channel error "
                                     "occurred, trying to reconnect: %s"), exc)
                        self.ensure_connection()
                except Exception:
                    LOG.warning(_LW("Unexpected error during heartbeart "
                                    "thread processing, retrying..."))
                    LOG.debug('Exception', exc_info=True)

            self._heartbeat_exit_event.wait(
                timeout=self._heartbeat_wait_timeout)
        self._heartbeat_exit_event.clear()
예제 #25
0
 def _complete_shutdown(self):
     """The AMQP Connection has closed, and the driver shutdown is complete.
     Clean up controller resources and exit.
     """
     self._socket_connection.close()
     self.processor.shutdown()
     LOG.info(_LI("Messaging has shutdown"))
예제 #26
0
 def _update_availability(self):
     fraction_of_available_instances = 0
     for redis_instance in self.matchmaker._redis_instances:
         if not redis_instance._is_available:
             is_available = \
                 self.matchmaker._check_availability(redis_instance)
             if is_available:
                 LOG.info(_LI("Redis host %s is available again."),
                          redis_instance._address)
                 fraction_of_available_instances += 1
                 # NOTE(gdavoian): mark an instance as available for
                 # writing to, but wait until all services register
                 # themselves in it for making the instance ready for
                 # reading from
                 redis_instance._is_available = True
                 redis_instance._ready_from = time.time() + \
                     self.conf.oslo_messaging_zmq.zmq_target_expire
         else:
             fraction_of_available_instances += 1
     fraction_of_available_instances /= \
         float(len(self.matchmaker._redis_instances))
     # NOTE(gdavoian): make the sleep time proportional to the number of
     # currently available instances
     self._sleep_for = max(
         self.conf.oslo_messaging_zmq.zmq_target_update *
         fraction_of_available_instances, self._MIN_SLEEP_FOR)
예제 #27
0
    def send(self, conn, msg, timeout=None):
        # TODO(sileht):
        # * use timeout parameter when available
        # * use rpc_timeout if not instead of hardcoded 60
        # * use @retrying
        timer = rpc_common.DecayingTimer(duration=60)
        timer.start()

        while True:
            try:
                super(RetryOnMissingExchangePublisher, self).send(conn, msg,
                                                                  timeout)
                return
            except conn.connection.channel_errors as exc:
                # NOTE(noelbk/sileht):
                # If rabbit dies, the consumer can be disconnected before the
                # publisher sends, and if the consumer hasn't declared the
                # queue, the publisher's will send a message to an exchange
                # that's not bound to a queue, and the message wll be lost.
                # So we set passive=True to the publisher exchange and catch
                # the 404 kombu ChannelError and retry until the exchange
                # appears
                if exc.code == 404 and timer.check_return() > 0:
                    LOG.info(_LI("The exchange %(exchange)s to send to "
                                 "%(routing_key)s doesn't exist yet, "
                                 "retrying...") % {
                                     'exchange': self.exchange,
                                     'routing_key': self.routing_key})
                    time.sleep(1)
                    continue
                raise
예제 #28
0
    def send(self, conn, msg, timeout=None):
        # TODO(sileht):
        # * use timeout parameter when available
        # * use rpc_timeout if not instead of hardcoded 60
        # * use @retrying
        timer = rpc_common.DecayingTimer(duration=60)
        timer.start()

        while True:
            try:
                super(RetryOnMissingExchangePublisher,
                      self).send(conn, msg, timeout)
                return
            except conn.connection.channel_errors as exc:
                # NOTE(noelbk/sileht):
                # If rabbit dies, the consumer can be disconnected before the
                # publisher sends, and if the consumer hasn't declared the
                # queue, the publisher's will send a message to an exchange
                # that's not bound to a queue, and the message wll be lost.
                # So we set passive=True to the publisher exchange and catch
                # the 404 kombu ChannelError and retry until the exchange
                # appears
                if exc.code == 404 and timer.check_return() > 0:
                    LOG.info(
                        _LI("The exchange %(exchange)s to send to "
                            "%(routing_key)s doesn't exist yet, "
                            "retrying...") % {
                                'exchange': self.exchange,
                                'routing_key': self.routing_key
                            })
                    time.sleep(1)
                    continue
                raise
 def __init__(self, conf, poller, server):
     super(RouterConsumer, self).__init__(conf, poller, server, zmq.ROUTER)
     self.matchmaker = server.matchmaker
     self.targets = []
     self.host = zmq_address.combine_address(self.conf.rpc_zmq_host,
                                             self.port)
     LOG.info(_LI("[%s] Run ROUTER consumer"), self.host)
예제 #30
0
    def receive_message(self, socket):
        try:
            reply_id = socket.recv()
            empty = socket.recv()
            assert empty == b'', 'Bad format: empty delimiter expected'
            msg_type = socket.recv_string()
            assert msg_type is not None, 'Bad format: msg type expected'

            msg_id = None
            if msg_type != zmq_names.CALL_TYPE:
                msg_id = socket.recv_string()

            context = socket.recv_pyobj()
            message = socket.recv_pyobj()
            LOG.info(_LI("Received %(msg_type)s message %(msg)s")
                     % {"msg_type": msg_type,
                        "msg": str(message)})

            if msg_type == zmq_names.CALL_TYPE:
                return zmq_incoming_message.ZmqIncomingRequest(
                    self.server, context, message, socket, reply_id,
                    self.poller)
            elif msg_type in (zmq_names.CAST_TYPES + zmq_names.NOTIFY_TYPES):
                return RouterIncomingMessage(
                    self.server, context, message, socket, reply_id,
                    msg_id, self.poller)
            else:
                LOG.error(_LE("Unknown message type: %s") % msg_type)

        except zmq.ZMQError as e:
            LOG.error(_LE("Receiving message failed: %s") % str(e))
    def _send_request(self, socket, request):

        super(PushPublisher, self)._send_request(socket, request)

        LOG.info(_LI("Publishing message %(message)s to a target %(target)s")
                 % {"message": request.message,
                    "target": request.target})
예제 #32
0
    def direct_send(self, msg_id, msg):
        """Send a 'direct' message."""

        timer = rpc_common.DecayingTimer(duration=60)
        timer.start()
        # NOTE(sileht): retry at least 60sec, after we have a good change
        # that the caller is really dead too...

        while True:
            try:
                self.publisher_send(DirectPublisher, msg_id, msg,
                                    error_callback=None)
                return
            except self.connection.channel_errors as exc:
                # NOTE(noelbk/sileht):
                # If rabbit dies, the consumer can be disconnected before the
                # publisher sends, and if the consumer hasn't declared the
                # queue, the publisher's will send a message to an exchange
                # that's not bound to a queue, and the message wll be lost.
                # So we set passive=True to the publisher exchange and catch
                # the 404 kombu ChannelError and retry until the exchange
                # appears
                if exc.code == 404 and timer.check_return() > 0:
                    LOG.info(_LI("The exchange to reply to %s doesn't "
                                 "exist yet, retrying...") % msg_id)
                    time.sleep(1)
                    continue
                self._log_publisher_send_error(msg_id, exc)
                raise
            except Exception as exc:
                self._log_publisher_send_error(msg_id, exc)
                raise
예제 #33
0
        def _get_single_host():
            hosts = self.get_hosts(target)
            try:
                if not hosts:
                    err_msg = "No hosts were found for target %s." % target
                    LOG.error(err_msg)
                    raise oslo_messaging.InvalidTarget(err_msg, target)

                if len(hosts) == 1:
                    host = hosts[0]
                    LOG.info(_LI(
                        "A single host %(host)s found for target %(target)s.")
                        % {"host": host, "target": target})
                else:
                    host = random.choice(hosts)
                    LOG.warning(_LW(
                        "Multiple hosts %(hosts)s were found for target "
                        " %(target)s. Using the random one - %(host)s.")
                        % {"hosts": hosts, "target": target, "host": host})
                return host
            except oslo_messaging.InvalidTarget as ex:
                if timeout:
                    raise oslo_messaging.MessagingTimeout()
                else:
                    raise ex
예제 #34
0
 def _complete_shutdown(self):
     """The AMQP Connection has closed, and the driver shutdown is complete.
     Clean up controller resources and exit.
     """
     self._socket_connection.close()
     self.processor.shutdown()
     LOG.info(_LI("Messaging has shutdown"))
    def receive_message(self, socket):
        try:
            reply_id = socket.recv()
            empty = socket.recv()
            assert empty == b'', 'Bad format: empty delimiter expected'
            msg_type = socket.recv_string()
            assert msg_type is not None, 'Bad format: msg type expected'

            msg_id = None
            if msg_type != zmq_names.CALL_TYPE:
                msg_id = socket.recv_string()

            context = socket.recv_pyobj()
            message = socket.recv_pyobj()
            LOG.info(_LI("Received %(msg_type)s message %(msg)s")
                     % {"msg_type": msg_type,
                        "msg": str(message)})

            if msg_type == zmq_names.CALL_TYPE:
                return zmq_incoming_message.ZmqIncomingRequest(
                    self.server, context, message, socket, reply_id,
                    self.poller)
            elif msg_type in (zmq_names.CAST_TYPES + zmq_names.NOTIFY_TYPES):
                return RouterIncomingMessage(
                    self.server, context, message, socket, reply_id,
                    msg_id, self.poller)
            else:
                LOG.error(_LE("Unknown message type: %s") % msg_type)

        except zmq.ZMQError as e:
            LOG.error(_LE("Receiving message failed: %s") % str(e))
예제 #36
0
    def __init__(self, conf, context, matchmaker):
        self.conf = conf
        self.context = context
        self.matchmaker = matchmaker

        LOG.info(_LI("Running %s proxy") % self.PROXY_TYPE)

        self.poller = zmq_async.get_poller()
    def _send_request(self, socket, request):

        socket.send(b'', zmq.SNDMORE)
        socket.send_pyobj(request)

        LOG.info(_LI("Sending message %(message)s to a target %(target)s")
                 % {"message": request.message,
                    "target": request.target})
예제 #38
0
 def __init__(self, conf, poller, server):
     super(PullConsumer, self).__init__(conf, poller, server, zmq.PULL)
     self.matchmaker = server.matchmaker
     self.host = zmq_address.combine_address(self.conf.rpc_zmq_host,
                                             self.port)
     self.targets = zmq_consumer_base.TargetsManager(
         conf, self.matchmaker, self.host, zmq.PULL)
     LOG.info(_LI("[%s] Run PULL consumer"), self.host)
예제 #39
0
 def __init__(self, conf, poller, server):
     super(PullConsumer, self).__init__(conf, poller, server, zmq.PULL)
     self.matchmaker = server.matchmaker
     self.host = zmq_address.combine_address(self.conf.rpc_zmq_host,
                                             self.port)
     self.targets = zmq_consumer_base.TargetsManager(
         conf, self.matchmaker, self.host, zmq.PULL)
     LOG.info(_LI("[%s] Run PULL consumer"), self.host)
예제 #40
0
 def run(self):
     try:
         request = self.queue.get(timeout=self.conf.rpc_poll_timeout)
         LOG.info(_LI("Redirecting request %s to TCP publisher ...")
                  % request)
         self.publisher.send_request(request)
     except six.moves.queue.Empty:
         return
    def listen(self, target):

        LOG.info(_LI("[%(host)s] Listen to target %(target)s"),
                 {'host': self.host, 'target': target})

        self.targets.append(target)
        self.matchmaker.register(target, self.host,
                                 zmq_names.socket_type_str(zmq.ROUTER))
예제 #42
0
    def run(self):
        request, socket = self.poller.poll(self.conf.rpc_poll_timeout)
        if request is None:
            return

        LOG.info(_LI("Received request and queue it: %s") % str(request))

        self.queue.put(request)
예제 #43
0
    def __init__(self, conf, context, matchmaker):
        self.conf = conf
        self.context = context
        self.matchmaker = matchmaker

        LOG.info(_LI("Running %s proxy") % self.PROXY_TYPE)

        self.poller = zmq_async.get_poller()
예제 #44
0
 def _reply_link_ready(self):
     """Invoked when the Replies reply link has become active.  At this
     point, we are ready to send/receive messages (via Task processing).
     """
     LOG.info(_LI("Messaging is active (%(hostname)s:%(port)s)"),
              {'hostname': self.hosts.current.hostname,
               'port': self.hosts.current.port})
     self._schedule_task_processing()
예제 #45
0
 def __init__(self, conf, poller, server):
     self.sockets_manager = zmq_publisher_base.SocketsManager(
         conf, server.matchmaker, zmq.ROUTER, zmq.DEALER)
     self.host = None
     super(DealerConsumer, self).__init__(conf, poller, server, zmq.DEALER)
     self.connection_updater = ConsumerConnectionUpdater(
         conf, self.matchmaker, self.socket)
     LOG.info(_LI("[%s] Run DEALER consumer"), self.host)
예제 #46
0
 def put(self, msg_id, message_data):
     queue = self._queues.get(msg_id)
     if not queue:
         LOG.info(_LI('No calling threads waiting for msg_id : %s'), msg_id)
         LOG.debug(' queues: %(queues)s, message: %(message)s',
                   {'queues': len(self._queues), 'message': message_data})
     else:
         queue.put(message_data)
예제 #47
0
 def put(self, msg_id, message_data):
     queue = self._queues.get(msg_id)
     if not queue:
         LOG.info(_LI('No calling threads waiting for msg_id : %s'), msg_id)
         LOG.debug(' queues: %(queues)s, message: %(message)s',
                   {'queues': len(self._queues), 'message': message_data})
     else:
         queue.put(message_data)
예제 #48
0
    def _publish_and_retry_on_missing_exchange(self,
                                               exchange,
                                               msg,
                                               routing_key=None,
                                               timeout=None):
        """Publisher that retry if the exchange is missing.
        """

        if not exchange.passive:
            raise RuntimeError("_publish_and_retry_on_missing_exchange() must "
                               "be called with an passive exchange.")

        # TODO(sileht): use @retrying
        # NOTE(sileht): no need to wait the application expect a response
        # before timeout is exshauted
        duration = (timeout
                    if timeout is not None else self.kombu_reconnect_timeout)

        timer = rpc_common.DecayingTimer(duration=duration)
        timer.start()

        while True:
            try:
                self._publish(exchange,
                              msg,
                              routing_key=routing_key,
                              timeout=timeout)
                return
            except self.connection.channel_errors as exc:
                # NOTE(noelbk/sileht):
                # If rabbit dies, the consumer can be disconnected before the
                # publisher sends, and if the consumer hasn't declared the
                # queue, the publisher's will send a message to an exchange
                # that's not bound to a queue, and the message wll be lost.
                # So we set passive=True to the publisher exchange and catch
                # the 404 kombu ChannelError and retry until the exchange
                # appears
                if exc.code == 404 and timer.check_return() > 0:
                    LOG.info(
                        _LI("The exchange %(exchange)s to send to "
                            "%(routing_key)s doesn't exist yet, "
                            "retrying...") % {
                                'exchange': exchange.name,
                                'routing_key': routing_key
                            })
                    time.sleep(0.25)
                    continue
                elif exc.code == 404:
                    msg = _("The exchange %(exchange)s to send to "
                            "%(routing_key)s still doesn't exist after "
                            "%(duration)s sec abandoning...") % {
                                'duration': duration,
                                'exchange': exchange.name,
                                'routing_key': routing_key
                            }
                    LOG.info(msg)
                    raise rpc_amqp.AMQPDestinationNotFound(msg)
                raise
예제 #49
0
 def _call_notify(self, ext, context, message, priority, retry,
                  accepted_drivers):
     """Emit the notification.
     """
     # accepted_drivers is passed in as a result of the map() function
     LOG.info(_LI("Routing '%(event)s' notification to '%(driver)s' "
                  "driver"),
              {'event': message.get('event_type'), 'driver': ext.name})
     ext.obj.notify(context, message, priority, retry)
 def __init__(self, conf, poller, server):
     self.reply_sender = zmq_senders.ReplySenderProxy(conf)
     self.sockets_manager = zmq_sockets_manager.SocketsManager(
         conf, server.matchmaker, zmq.DEALER)
     self.host = None
     super(DealerConsumer, self).__init__(conf, poller, server, zmq.DEALER)
     self.connection_updater = ConsumerConnectionUpdater(
         conf, self.matchmaker, self.socket)
     LOG.info(_LI("[%s] Run DEALER consumer"), self.host)
예제 #51
0
 def put(self, msg_id, message_data):
     queue = self._queues.get(msg_id)
     if not queue:
         LOG.info(_LI("No calling threads waiting for msg_id : %s"), msg_id)
         LOG.debug(
             " queues: %(queues)s, message: %(message)s", {"queues": len(self._queues), "message": message_data}
         )
     else:
         queue.put(message_data)
 def _call_notify(self, ext, context, message, priority, retry,
                  accepted_drivers):
     """Emit the notification.
     """
     # accepted_drivers is passed in as a result of the map() function
     LOG.info(_LI("Routing '%(event)s' notification to '%(driver)s' "
                  "driver"),
              {'event': message.get('event_type'), 'driver': ext.name})
     ext.obj.notify(context, message, priority, retry)