preface

The previous chapter covered some of the pros and cons of microservices, so how

A, goals,

Two, the use of steps

1. Install the consul

We can directly use the official binary file to install and deploy, and its official website address iswww.consul.io/downloads After downloading for the executable file, in our development test process, can be used directlyconsul agent -devCommand to start Consul for a single node

This can be seen in the startup print logAgent: Started HTTP Server on 127.0.0.1:8500 (TCP), we can access it directly in the browser127.0.0.1:8500You can see the followingHere our Consul has been successfully launched

2. Service registration

In network programming, IP, PORT and PROTOCOL of the project are generally provided. In service governance, we also need to know the corresponding service name, instance name and some customized extension information

The ServiceInstance interface is used here to specify some of the information required to register the service

class ServiceInstance:

    def __init__(self, service_id: str, host: str, port: int, secure: bool = False, metadata: dict = None,
                 instance_id: str = None) :
        self.service_id = service_id
        self.host = host
        self.port = port
        self.secure = secure
        self.metadata = metadata
        self.instance_id = instance_id

    def get_instance_id(self) :
        return
Copy the code

Define a base class

The necessary information of the services that need to be registered is specified above. The methods of service registration and deletion are defined below to facilitate the implementation of Eureka and Redis in the future

import abc


class ServiceRegistry(abc.ABC):

    @abc.abstractmethod
    def register(self, service_instance: ServiceInstance):
        pass

    @abc.abstractmethod
    def deregister(self):
        pass
Copy the code

The specific implementation

Because Consul provides an HTTP interface to operate on Consul, we can also use HTTP requests for registration and culling operations, Specific HTTP interface documentation see https://www.consul.io/api-docs, consul did not provide the implementation of the Python language, here use Python – consul to access the consul

import consul


class ConsulServiceRegistry(ServiceRegistry) :
    _consul = None
    _instance_id = None

    def __init__(self, host: str, port: int, token: str = None) :
        self.host = host
        self.port = port
        self.token = token
        self._consul = consul.Consul(host, port, token=token)

    def register(self, service_instance: ServiceInstance) :
        schema = "http"
        if service_instance.secure:
            schema = "https"
        check = consul.Check.http(f'{schema}:{service_instance.host}:{service_instance.port}/actuator/health'."1s"."3s"."10s")
        self._consul.agent.service.register(service_instance.service_id,
                                            service_id=service_instance.instance_id,
                                            address=service_instance.host,
                                            port=service_instance.port,
                                            check=check)
        self._instance_id = service_instance.instance_id

    def deregister(self) :
        if self._instance_id:
            self._consul.agent.service.deregister(service_id=self._instance_id)
            self._instance_id = None
Copy the code

3. Service discovery

In service discovery, two approaches are typically required

  1. Get a list of all services
  2. Gets information about all instances of the specified service

Base class definition

import abc


class DiscoveryClient(abc.ABC) :

    @abc.abstractmethod
    def get_services(self) - >list:
        pass

    @abc.abstractmethod
    def get_instances(self, service_id: str) - >list:
        pass
Copy the code

The specific implementation

Let’s implement it

This is a simplified version, so some parameters are written out and can be modified if necessary

import consul


class ConsulServiceDiscovery(DiscoveryClient) :

    _consul = None

    def __init__(self, host: str, port: int, token: str = None) :
        self.host = host
        self.port = port
        self.token = token
        self._consul = consul.Consul(host, port, token=token)

    def get_services(self) - >list:
        return self._consul.catalog.services()[1].keys()

    def get_instances(self, service_id: str) - >list:
        origin_instances = self._consul.catalog.service(service_id)[1]
        result = []
        for oi in origin_instances:
            result.append(ServiceInstance(
                oi.get('ServiceName'),
                oi.get('ServiceAddress'),
                oi.get('ServicePort'),
                oi.get('ServiceTags'),
                oi.get('ServiceMeta'),
                oi.get('ServiceID')))return result

Copy the code

Test cases

import unittest
from random import random


class MyTestCase(unittest.TestCase) :
    def test_consul_register(self) :
        instance = ServiceInstance("abc"."127.0.0.1".8000, instance_id=f'abc_{random()}')

        registry = ConsulServiceRegistry("127.0.0.1".8500)
        discovery = ConsulServiceDiscovery("127.0.0.1".8500)
        registry.register(instance)
        print(discovery.get_services())
        print(discovery.get_instances("abc"))
        self.assertEqual(True.True)


if __name__ == '__main__':
    unittest.main()
Copy the code

conclusion

Consul API can be used to implement consul based service discovery, and HTTP RPC can be used to implement service invocation. In the following chapter, we will briefly discuss how go initiates HTTP requests, paving the way for RPC

See github.com/zhangyunan1…

reference

  • www.consul.io/api-docs
  • Github.com/hashicorp/c…