nameko 的內聯繫結和 Dependency 解讀

ponponon發表於2022-12-15

下面這樣的程式碼樣例是一個典型的 nameko 例子

class AddService:
    name = 'add_service'

    dispatcher = EventDispatcher()

    @event_handler('hi_api', 'rubbish')
    def receive(self, message: str):
        self.dispatcher('to_download', message)

你有好奇過 dispatcher = EventDispatcher() 是怎麼拿到 amqp_uri、connection 這些資訊的嗎?

用你那個貧瘠的大腦好好思考一下,是不是很神奇,是不是驚為天人?

因為這裡面沒有任務的『繼承』

所以是怎麼實現的呢?看看標題就是知道了,必然是跟 nameko 的 Dependency 這個概念有關係。

多說懶得說,自己看原始碼

為了幫你節約時間,我先貼幾個關鍵原始碼

先來看看 EventDispatcher 的繼承關係,理清脈絡

圖片.png

從圖中可知,EventDispatcher 是 DependencyProvider 的子子類,一切的關鍵就是這個 DependencyProvider

讓我們來看看 DependencyProvider 的原始碼

site-packages/nameko/containers.py

class ServiceContainer(object):

    def __init__(self, service_cls, config):

        self.service_cls = service_cls
        self.config = config

        self.service_name = get_service_name(service_cls)
        self.shared_extensions = {}

        self.max_workers = (
            config.get(MAX_WORKERS_CONFIG_KEY) or DEFAULT_MAX_WORKERS)

        self.serializer, self.accept = serialization.setup(self.config)

        self.entrypoints = SpawningSet()
        self.dependencies = SpawningSet()
        self.subextensions = SpawningSet()

        for attr_name, dependency in inspect.getmembers(service_cls,
                                                        is_dependency):
            bound = dependency.bind(self.interface, attr_name)
            self.dependencies.add(bound)
            self.subextensions.update(iter_extensions(bound))

        for method_name, method in inspect.getmembers(service_cls, is_method):
            entrypoints = getattr(method, ENTRYPOINT_EXTENSIONS_ATTR, [])
            for entrypoint in entrypoints:
                bound = entrypoint.bind(self.interface, method_name)
                self.entrypoints.add(bound)
                self.subextensions.update(iter_extensions(bound))

        self.started = False
        self._worker_pool = GreenPool(size=self.max_workers)

        self._worker_threads = {}
        self._managed_threads = {}
        self._being_killed = False
        self._died = Event()

關鍵是這部分

for attr_name, dependency in inspect.getmembers(service_cls,
                                                is_dependency):
    bound = dependency.bind(self.interface, attr_name)
    self.dependencies.add(bound)
    self.subextensions.update(iter_extensions(bound))

相關文章