kombu transport 查找的处理
简单说明下kombu transport查找的处理,方便学习自定义broker的处理
Connection 处理
def __init__(self, hostname='localhost', userid=None,
password=None, virtual_host=None, port=None, insist=False,
ssl=False, transport=None, connect_timeout=5,
transport_options=None, login_method=None, uri_prefix=None,
heartbeat=0, failover_strategy='round-robin',
alternates=None, **kwargs):
alt = [] if alternates is None else alternates
# have to spell the args out, just to get nice docstrings :(
params = self._initial_params = {
'hostname': hostname, 'userid': userid,
'password': password, 'virtual_host': virtual_host,
'port': port, 'insist': insist, 'ssl': ssl,
'transport': transport, 'connect_timeout': connect_timeout,
'login_method': login_method, 'heartbeat': heartbeat
}
if hostname and not isinstance(hostname, str):
alt.extend(hostname)
hostname = alt[0]
params.update(hostname=hostname)
if hostname:
if ';' in hostname:
alt = hostname.split(';') + alt
hostname = alt[0]
params.update(hostname=hostname)
if '://' in hostname and '+' in hostname[:hostname.index('://')]:
# e.g. sqla+mysql://root:masterkey@localhost/
params['transport'], params['hostname'] = \
hostname.split('+', 1)
self.uri_prefix = params['transport']
elif '://' in hostname:
transport = transport or urlparse(hostname).scheme
if not get_transport_cls(transport).can_parse_url:
# we must parse the URL
url_params = parse_url(hostname)
params.update(
dictfilter(url_params),
hostname=url_params['hostname'],
)
params['transport'] = transport
self._init_params(**params)
get_transport_cls 处理
def get_transport_cls(transport: str | None = None) -> str | None:
"""Get transport class by name.
The transport string is the full path to a transport class, e.g.::
"kombu.transport.pyamqp:Transport"
If the name does not include `"."` (is not fully qualified),
the alias table will be consulted.
"""
if transport not in _transport_cache:
# resolve_transport 此处会进行解析处理
_transport_cache[transport] = resolve_transport(transport)
return _transport_cache[transport]
resolve_transport 的处理
def resolve_transport(transport: str | None = None) -> str | None:
"""Get transport by name.
Arguments:
---------
transport (Union[str, type]): This can be either
an actual transport class, or the fully qualified
path to a transport class, or the alias of a transport.
"""
if isinstance(transport, str):
try:
transport = TRANSPORT_ALIASES[transport]
except KeyError:
if '.' not in transport and ':' not in transport:
from kombu.utils.text import fmatch_best
alt = fmatch_best(transport, TRANSPORT_ALIASES)
if alt:
raise KeyError(
'No such transport: {}. Did you mean {}?'.format(
transport, alt))
raise KeyError(f'No such transport: {transport}')
else:
if callable(transport):
transport = transport()
# symbol_by_name 比较有意思可以进行一个额外的检查处理,比如基于包格式的
return symbol_by_name(transport)
return transport
symbol_by_name 处理(可以支持类似proj.transports.MyTransport://localhost 格式的处理)
def symbol_by_name(name, aliases=None, imp=None, package=None,
sep='.', default=None, **kwargs):
"""Get symbol by qualified name.
The name should be the full dot-separated path to the class::
modulename.ClassName
Example::
celery.concurrency.processes.TaskPool
^- class name
or using ':' to separate module and symbol::
celery.concurrency.processes:TaskPool
If `aliases` is provided, a dict containing short name/long name
mappings, the name is looked up in the aliases first.
Examples
--------
>>> symbol_by_name('celery.concurrency.processes.TaskPool')
<class 'celery.concurrency.processes.TaskPool'>
>>> symbol_by_name('default', {
... 'default': 'celery.concurrency.processes.TaskPool'})
<class 'celery.concurrency.processes.TaskPool'>
# Does not try to look up non-string names.
>>> from celery.concurrency.processes import TaskPool
>>> symbol_by_name(TaskPool) is TaskPool
True
"""
aliases = {} if not aliases else aliases
if imp is None:
imp = importlib.import_module
if not isinstance(name, str):
return name # already a class
name = aliases.get(name) or name
sep = ':' if ':' in name else sep
module_name, _, cls_name = name.rpartition(sep)
if not module_name:
cls_name, module_name = None, package if package else cls_name
try:
try:
module = imp(module_name, package=package, **kwargs)
except ValueError as exc:
reraise(ValueError,
ValueError(f"Couldn't import {name!r}: {exc}"),
sys.exc_info()[2])
return getattr(module, cls_name) if cls_name else module
except (ImportError, AttributeError):
if default is None:
raise
return default
说明
以上只是结合代码简单说明下kombu 对于transport 协议具体实现的查找处理,了解处理可以更好的学习内部处理
参考资料
https://github.com/celery/kombu/blob/5a88a28f31ab958072910d6f40f022296bea720c/kombu/connection.py