List running services (service discovery)

Hi,

I’ve found a thread that shows how to discover a service methods.

But now, I would like to know if it is possible to list available services?
I’ve found that thread, which shows that it is possible to list services by querying rabbitmq queues. But is there a better way to do it?

Thanks,

Hi,
We’ve also been looking for a way to do service discovery at Emplocity. In our case we decided that asking RabbitMQ management plugin for a list of queues was good enough, so here’s a code snippet that does just that (using pyrabbit. We’re planning to properly opensource it some day, but here’s the gist of it:

import logging
from typing import List

from nameko.containers import WorkerContext
from nameko.extensions import DependencyProvider
from pyrabbit.api import Client


logger = logging.getLogger(__name__)


class ServiceDiscovery:
    """
    Provides introspection for nameko services defined on the RabbitMQ cluster.
    """

    def __init__(self, client: Client):
        self.client = client
        logger.info(f"Service discovery ready: host={self.client.host}")

    def find_services(self) -> List[str]:
        """
        Returns a list of service names which are available on the network.
        """
        return [
            queue["name"].replace("rpc-", "")
            for queue in self.client.get_queues()
            if self.is_nameko_service(queue["name"])
        ]

    def is_nameko_service(self, queue_name: str) -> bool:
        """
        Checks if queue name matches pattern used by nameko for service queues.
        """
        return queue_name.startswith("rpc-") and queue_name.endswith("_service")


class ServiceDiscoveryProvider(DependencyProvider):
    def __init__(self, management_host: str, username: str, password: str):
        self.management_host = management_host
        self.username = username
        self.password = password

    def setup(self):
        self.client = Client(self.management_host, self.username, self.password)
        self.discovery = ServiceDiscovery(self.client)

    def get_dependency(self, worker_ctx: WorkerContext) -> ServiceDiscovery:
        return self.discovery

You can use it like this:

class MyService(Service):
    name = "my_service"
    service_discovery = ServiceDiscoveryProvider(
        management_host="rabbitmq:15672",
        username="guest",
        password="guest",
    )

    @rpc
    def my_method(self) -> None:
        service_names = self.service_discovery.find_services()
        # ...
2 Likes

Hi zsiciarz,

Thanks for your answer.

I’ve changed is_nameko_service method a little, because we don’t have the same naming convention (our services don’t end with “_service”), otherwise your service discovery provider is exactly what I was looking for!
It works like a charm :slight_smile:

Thanks a lot for your help,
Anthony

1 Like