def send_request(self, multipart_message): envelope = multipart_message[zmq_names.MULTIPART_IDX_ENVELOPE] LOG.debug("Envelope: %s" % envelope) target = envelope[zmq_names.FIELD_TARGET] dealer_socket = self._check_hosts_connections( target, zmq_names.socket_type_str(zmq.ROUTER)) 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.debug("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)
def listen(self, target): LOG.info("[%s] Listen to target %s" % (self.host, target)) self.targets.append(target) self.matchmaker.register(target, self.host, zmq_names.socket_type_str(zmq.ROUTER))
def cleanup(self): if self.updater: self.updater.stop() for target in self.targets: self.matchmaker.unregister( target, self.host, zmq_names.socket_type_str(self.socket_type))
def send_request(self, multipart_message): envelope = multipart_message[zmq_names.MULTIPART_IDX_ENVELOPE] LOG.debug("Envelope: %s" % envelope) target = envelope[zmq_names.FIELD_TARGET] dealer_socket = self._check_hosts_connections( target, zmq_names.socket_type_str(zmq.ROUTER)) 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.debug( "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)
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.debug("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 })
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))
def send_request(self, request): if request.msg_type not in zmq_names.NOTIFY_TYPES: raise zmq_publisher_base.UnsupportedSendPattern(request.msg_type) pub_socket = self._check_hosts_connections( request.target, zmq_names.socket_type_str(zmq.SUB)) self._send_request(pub_socket, request)
def _fetch_hosts(self, target, get_hosts, get_hosts_retry): key = str(target) if key not in self.routing_table: try: hosts = get_hosts_retry( target, zmq_names.socket_type_str(zmq.DEALER)) self.routing_table[key] = (hosts, time.time()) except retrying.RetryError: LOG.warning(_LW("Matchmaker contains no hosts for target %s") % key) else: try: hosts = get_hosts( target, zmq_names.socket_type_str(zmq.DEALER)) self.routing_table[key] = (hosts, time.time()) except zmq_matchmaker_base.MatchmakerUnavailable: LOG.warning(_LW("Matchmaker contains no hosts for target %s") % key)
def _fetch_fanout_hosts_from_matchmaker(self, target, target_key): with self._lock: if not self.routing_table.contains(target_key): LOG.debug("Target %s is not in cache. Check matchmaker server." % target_key) hosts = self.matchmaker.get_hosts_fanout( target, zmq_names.socket_type_str(self.listener_type)) LOG.debug("Received hosts %s" % hosts) self.routing_table.update_hosts(target_key, hosts)
def _fetch_round_robin_hosts_from_matchmaker(self, target): target_key = zmq_address.target_to_key( target, zmq_names.socket_type_str(self.listener_type)) LOG.debug("Processing target %s for round-robin." % target_key) if target_key not in self.round_robin_targets: with self._lock: if target_key not in self.round_robin_targets: LOG.debug("Target %s is not in cache. Check matchmaker " "server." % target_key) hosts = self.matchmaker.get_hosts_retry( target, zmq_names.socket_type_str(self.listener_type)) LOG.debug("Received hosts %s" % hosts) self.routing_table.update_hosts(target_key, hosts) self.round_robin_targets[target_key] = \ self.routing_table.get_hosts_round_robin(target_key) return target_key
def _update_targets(self): with self.targets_lock: for target in self.targets: self.matchmaker.register( target, self.host, zmq_names.socket_type_str(self.socket_type)) # Update target-records once per half expiration time time.sleep(self.conf.zmq_target_expire / 2)
def run_loop(self): try: request = self.queue.get(timeout=self.conf.rpc_poll_timeout) except self.empty_except: return socket = self._check_hosts_connections(request.target, zmq_names.socket_type_str(zmq.ROUTER)) self._do_send_request(socket, request) self.reply_waiter.poll_socket(socket)
def get_fanout_hosts(self, target): target_key = zmq_address.target_to_key( target, zmq_names.socket_type_str(self.listener_type)) LOG.debug("Processing target %s for fanout." % target_key) if not self.routing_table.contains(target_key): self._fetch_fanout_hosts_from_matchmaker(target, target_key) return self.routing_table.get_hosts_fanout(target_key)
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))
def acquire_connection(self, request): target_key = zmq_address.target_to_key( request.target, zmq_names.socket_type_str(zmq.ROUTER)) if request.msg_type in zmq_names.MULTISEND_TYPES: hosts = self.routing_table.get_fanout_hosts(request.target) return self.fanout_sockets.get_cached_socket(target_key, hosts, immediate=False) else: hosts = self.routing_table.get_all_round_robin_hosts( request.target) return self.sockets_manager.get_cached_socket(target_key, hosts)
def run_loop(self): try: request = self.queue.get(timeout=self.conf.rpc_poll_timeout) except self.empty_except: return socket = self._check_hosts_connections( request.target, zmq_names.socket_type_str(zmq.ROUTER)) self._do_send_request(socket, request) self.reply_waiter.poll_socket(socket)
class TestZmqAddress(test_utils.BaseTestCase): scenarios = [('router', { 'listener_type': zmq_names.socket_type_str(zmq.ROUTER) }), ('dealer', { 'listener_type': zmq_names.socket_type_str(zmq.DEALER) })] @testtools.skipIf(zmq is None, "zmq not available") def test_target_to_key_topic_only(self): target = oslo_messaging.Target(topic='topic') key = zmq_address.target_to_key(target, self.listener_type) self.assertEqual(self.listener_type + '/topic', key) @testtools.skipIf(zmq is None, "zmq not available") def test_target_to_key_topic_server_round_robin(self): target = oslo_messaging.Target(topic='topic', server='server') key = zmq_address.target_to_key(target, self.listener_type) self.assertEqual(self.listener_type + '/topic/server', key) @testtools.skipIf(zmq is None, "zmq not available") def test_target_to_key_topic_fanout(self): target = oslo_messaging.Target(topic='topic', fanout=True) key = zmq_address.target_to_key(target, self.listener_type) self.assertEqual(self.listener_type + '/topic', key) @testtools.skipIf(zmq is None, "zmq not available") def test_target_to_key_topic_server_fanout(self): target = oslo_messaging.Target(topic='topic', server='server', fanout=True) key = zmq_address.target_to_key(target, self.listener_type) self.assertEqual(self.listener_type + '/topic', key) @testtools.skipIf(zmq is None, "zmq not available") def test_target_to_key_topic_server_fanout_no_prefix(self): target = oslo_messaging.Target(topic='topic', server='server', fanout=True) key = zmq_address.target_to_key(target) self.assertEqual('topic', key)
def connect_to_address(self, address): stype = zmq_names.socket_type_str(self.socket_type) try: LOG.info(_LI("Connecting %(stype)s id %(id)s to %(address)s"), {"stype": stype, "id": self.handle.identity, "address": address}) self.connect(address) except zmq.ZMQError as e: errmsg = _LE("Failed connecting %(stype) to %(address)s: %(e)s")\ % (stype, address, e) LOG.error(_LE("Failed connecting %(stype) to %(address)s: %(e)s"), (stype, address, e)) raise rpc_common.RPCException(errmsg)
def subscribe_socket(self, socket_type): try: socket = zmq_socket.ZmqRandomPortSocket(self.conf, self.context, socket_type) self.sockets.append(socket) LOG.debug( "Run %(stype)s consumer on %(addr)s:%(port)d", {"stype": zmq_names.socket_type_str(socket_type), "addr": socket.bind_address, "port": socket.port}, ) self.host = zmq_address.combine_address(self.conf.rpc_zmq_host, socket.port) self.poller.register(socket, self.receive_message) return socket except zmq.ZMQError as e: errmsg = _LE("Failed binding to port %(port)d: %(e)s") % (self.port, e) LOG.error(_LE("Failed binding to port %(port)d: %(e)s"), (self.port, e)) raise rpc_common.RPCException(errmsg)
def connect_to_address(self, address): if address in self.connections: return stype = zmq_names.socket_type_str(self.socket_type) try: LOG.info(_LI("Connecting %(stype)s id %(id)s to %(address)s"), {"stype": stype, "id": self.handle.identity, "address": address}) self.connect(address) except zmq.ZMQError as e: errmsg = _LE("Failed connecting %(stype)s to %(address)s: %(e)s") \ % {"stype": stype, "address": address, "e": e} LOG.error(_LE("Failed connecting %(stype)s to %(address)s: %(e)s"), {"stype": stype, "address": address, "e": e}) raise rpc_common.RPCException(errmsg)
def _connect_to_host(self, socket, host, target): address = zmq_address.get_tcp_direct_address(host) LOG.info(address) stype = zmq_names.socket_type_str(self.socket_type) try: LOG.info(_LI("Connecting %(stype)s to %(address)s for %(target)s") % {"stype": stype, "address": address, "target": target}) socket.connect(address) except zmq.ZMQError as e: errmsg = _LE("Failed connecting %(stype) to %(address)s: %(e)s")\ % (stype, address, e) LOG.error(_LE("Failed connecting %(stype) to %(address)s: %(e)s") % (stype, address, e)) raise rpc_common.RPCException(errmsg)
def subscribe_socket(self, socket_type): try: socket = zmq_socket.ZmqRandomPortSocket( self.conf, self.context, socket_type) self.sockets.append(socket) self.poller.register(socket, self.receive_message) LOG.info(_LI("Run %(stype)s consumer on %(addr)s:%(port)d"), {"stype": zmq_names.socket_type_str(socket_type), "addr": socket.bind_address, "port": socket.port}) return socket except zmq.ZMQError as e: errmsg = _LE("Failed binding to port %(port)d: %(e)s")\ % (self.port, e) LOG.error(_LE("Failed binding to port %(port)d: %(e)s") % (self.port, e)) raise rpc_common.RPCException(errmsg)
def send_request(self, request): if request.msg_type == zmq_names.CALL_TYPE: raise zmq_publisher_base.UnsupportedSendPattern(request.msg_type) push_socket = self._check_hosts_connections( request.target, zmq_names.socket_type_str(zmq.PULL)) if not push_socket.connections: LOG.warning(_LW("Request %s was dropped because no connection") % request.msg_type) return if request.msg_type in zmq_names.MULTISEND_TYPES: for _ in range(push_socket.connections_count()): self._send_request(push_socket, request) else: self._send_request(push_socket, request)
def connect_to_address(self, address): stype = zmq_names.socket_type_str(self.socket_type) try: LOG.info(_LI("Connecting %(stype)s to %(address)s"), {"stype": stype, "address": address}) if six.PY3: self.setsockopt_string(zmq.IDENTITY, str(uuid.uuid1())) else: self.handle.identity = str(uuid.uuid1()) self.connect(address) except zmq.ZMQError as e: errmsg = _LE("Failed connecting %(stype) to %(address)s: %(e)s")\ % (stype, address, e) LOG.error(_LE("Failed connecting %(stype) to %(address)s: %(e)s"), (stype, address, e)) raise rpc_common.RPCException(errmsg)
def send_request(self, request): self._check_request_pattern(request) dealer_socket = self._check_hosts_connections(request.target, zmq_names.socket_type_str(zmq.ROUTER)) 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"), request.msg_type) return if request.msg_type in zmq_names.MULTISEND_TYPES: for _ in range(dealer_socket.connections_count()): self._send_request(dealer_socket, request) else: self._send_request(dealer_socket, request)
def _update_target(self): try: self.matchmaker.register( self.target, self.host, zmq_names.socket_type_str(self.socket_type), expire=self.conf.oslo_messaging_zmq.zmq_target_expire) if self._sleep_for != \ self.conf.oslo_messaging_zmq.zmq_target_update: self._sleep_for = \ self.conf.oslo_messaging_zmq.zmq_target_update LOG.info(_LI("Falling back to the normal update %d sec") % self._sleep_for) except zmq_matchmaker_base.MatchmakerUnavailable: # Update target frequently until first successful update # After matchmaker is back update normally as of config self._sleep_for = 10 LOG.warning(_LW("Failed connecting to the Matchmaker, " "update each %d sec") % self._sleep_for)
def send_request(self, request): self._check_request_pattern(request) dealer_socket = self._check_hosts_connections( request.target, zmq_names.socket_type_str(zmq.ROUTER)) 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"), request.msg_type) return if request.msg_type in zmq_names.MULTISEND_TYPES: for _ in range(dealer_socket.connections_count()): self._send_request(dealer_socket, request) else: self._send_request(dealer_socket, request)
def _update_target(self): try: self.matchmaker.register( self.target, self.host, zmq_names.socket_type_str(self.socket_type), expire=self.conf.oslo_messaging_zmq.zmq_target_expire) if self._sleep_for != \ self.conf.oslo_messaging_zmq.zmq_target_update: self._sleep_for = \ self.conf.oslo_messaging_zmq.zmq_target_update LOG.info( _LI("Falling back to the normal update %d sec") % self._sleep_for) except zmq_matchmaker_base.MatchmakerUnavailable: # Update target frequently until first successful update # After matchmaker is back update normally as of config self._sleep_for = 10 LOG.warning( _LW("Failed connecting to the Matchmaker, " "update each %d sec") % self._sleep_for)
def stop(self): super(TargetUpdater, self).stop() self.matchmaker.unregister( self.target, self.host, zmq_names.socket_type_str(self.socket_type))
def _fetch_hosts(self, target): self.routing_table[str(target)] = (self.matchmaker.get_hosts( target, zmq_names.socket_type_str(zmq.DEALER)), time.time())
def get_hosts(self, target): return self.matchmaker.get_hosts_retry( target, zmq_names.socket_type_str(self.listener_type))
def type_name(self): return zmq_names.socket_type_str(self.socket_type)
def cleanup(self): super(RouterConsumer, self).cleanup() for target in self.targets: self.matchmaker.unregister(target, self.host, zmq_names.socket_type_str(zmq.ROUTER))
def _get_hosts_and_connect(self, socket, target): hosts = self.matchmaker.get_hosts( target, zmq_names.socket_type_str(self.listener_type)) for host in hosts: socket.connect_to_host(host) self._track_socket(socket, target)
def listen(self, target): with self.targets_lock: self.targets.append(target) self.matchmaker.register( target, self.host, zmq_names.socket_type_str(self.socket_type))
def _update_target(self): self.matchmaker.register( self.target, self.host, zmq_names.socket_type_str(self.socket_type), expire=self.conf.zmq_target_expire)
def _resolve_host_address(self, target, timeout=0): host = self.matchmaker.get_single_host( target, zmq_names.socket_type_str(zmq.ROUTER), timeout) return zmq_address.get_tcp_direct_address(host)
def _update_target(self): self.matchmaker.register(self.target, self.host, zmq_names.socket_type_str(self.socket_type)) time.sleep(self.conf.zmq_target_expire / 2)
def stop(self): super(TargetUpdater, self).stop() self.matchmaker.unregister(self.target, self.host, zmq_names.socket_type_str(self.socket_type))
def get_hosts(self, target): return self.matchmaker.get_hosts( target, zmq_names.socket_type_str(self.listener_type))