Skip to content

Service Discovery

Service discovery in ASAB Maestro is a group of techniques how to find and reach specific service in the cluster network.

Identity

Each instance is provided with three identifiers:

  • NODE_ID - identifier of the cluster node
  • SERVICE_ID - name of the service
  • INSTANCE_ID - identifier of the instance

This allows to search the services in various situations by the same names.

NGINX proxy server

nginx:api option in the descriptors creates standardized Nginx configuration.

Example of ASAB Library descriptor:

define:
  type: rc/descriptor
  name: ASAB Library

descriptor:
  image: docker.teskalabs.com/asab/asab-library

  volumes:
    - "{{SITE}}/{{INSTANCE_ID}}/conf:/conf:ro"
    - "{{SLOW_STORAGE}}/{{INSTANCE_ID}}:/var/lib/asab-library"

asab:
  configname: conf/asab-library.conf
  config: {}

nginx:
  api: 8893

All instances are supplied with a location inside the Nginx configuration.

location /api/<instance_id> {
    ...
}

Moreover, each service has its location and respective upstreams record. Your request is proxied to a random instance of the service.

location /api/<service_id> {
    ...
}

These locations are accessible in the:

  • HTTPS server behind OAuth2 introspection (when authorization server like SeaCat Auth is installed) to be used mainly by Web UI,
  • and the internal server. This one is accessible from within the cluster, must not be open to the internet and serves for internal communication of backend services.

PUBLIC_URL

It is crucial for the HTTPS server functionality and successful authorization to set PUBLIC_URL parameter in the model.

define:
    type: rc/model

services:
    zoonavigator:
        instances: {1: {node: "lmc01"} }
params:
    PUBLIC_URL: "https://maestro.logman.io"

Custom /etc/hosts

Each running container is supplied by custom and automatically actualized configuration inside /etc/hosts. IP address of each service or instance is resolved using respective INSTANCE_ID or SERVICE_ID.

Example of /etc/hosts inside the container:

# This file is generated by ASAB Remote Control
# WARNING: DON'T MODIFY IT MANUALLY !!!

127.0.0.1   localhost
::1         localhost ip6-localhost ip6-loopback
fe00::0     ip6-localnet
ff00::0     ip6-mcastprefix
ff02::1     ip6-allnodes
ff02::2     ip6-allrouters

# Nodes
10.35.58.41     lmc02
10.35.58.194    lmc03
10.35.58.88     lmc01

# Instances
10.35.58.88     zoonavigator-1
10.35.58.88     mongo-1
10.35.58.41     mongo-2
10.35.58.194    mongo-3
10.35.58.88     seacat-auth-1
10.35.58.88     nginx-1
10.35.58.88     asab-config-1
10.35.58.41     asab-config-2
10.35.58.194    asab-config-3
10.35.58.88     asab-governator-1
10.35.58.41     asab-governator-2
10.35.58.194    asab-governator-3
10.35.58.88     asab-library-1
10.35.58.41     asab-library-2
10.35.58.194    asab-library-3
10.35.58.88     asab-remote-control-1
10.35.58.41     asab-remote-control-2
10.35.58.194    asab-remote-control-3
10.35.58.88     zookeeper-1
10.35.58.41     zookeeper-2
10.35.58.194    zookeeper-3

# Services
10.35.58.88     zoonavigator
10.35.58.88     mongo
10.35.58.41     mongo
10.35.58.194    mongo
10.35.58.88     seacat-auth
10.35.58.88     nginx
10.35.58.88     asab-config
10.35.58.41     asab-config
10.35.58.194    asab-config
10.35.58.88     asab-governator
10.35.58.41     asab-governator
10.35.58.194    asab-governator
10.35.58.88     asab-library
10.35.58.41     asab-library
10.35.58.194    asab-library
10.35.58.88     asab-remote-control
10.35.58.41     asab-remote-control
10.35.58.194    asab-remote-control
10.35.58.88     zookeeper
10.35.58.41     zookeeper
10.35.58.194    zookeeper

Consensus and data advertised by running ASAB microservices

Each ASAB microservice advertise data about itself to the consensus. This data contain NODE_ID, SERVICE_ID and INSTANCE_ID resolved thanks to the custom /etc/hosts and port. ASAB framework also offers boiler plate code to use aiohttp client requests with only the SERVICE_ID or INSTANCE_ID of the target service. Thus, each ASAB microservice has tools to access any other ASAB microservice in the cluster.

Example of python code within ASAB application using Discovery Service

    async def proxy_to_iris(self, json_data):
        async with self.App.DiscoveryService.session() as session:
            try:
                async with session.put("http://asab-iris.service_id.asab/send_mail", json=json_data) as resp:
                    response = await resp.json()
            except asab.api.discovery.NotDiscoveredError:
                raise RuntimeError("ASAB Iris could not be reached.")