参考网址
blog.csdn.net/WenWu_Both/…
安装
pip install python-consul
注意:是python-consul,而不是consul
0前言
如果想在consul上进行服务的注册和服务发现等,
目前已经有成熟的,已经和封装好的相关的逻辑,可以直接使用。
1/服务实例
首先我们先定义服务实例
class ServiceInstance:
def __init__(self, service_id:str, host: str, port: int, tags: list = None,
metadata: dict = None, instance_id: str = None):
self.service_id = service_id
self.host = host
self.port = port
self.tags = tags
self.metadata = metadata
self.instance_id = instance_id
def get_instance_id(self):
return
2/服务注册
接着我们定义下注册服务的接口:
import abc
class ServiceRegistry(abc.ABC):
@abc.abstractmethod
def register(self, service_instance: ServiceInstance):
pass
@abc.abstractmethod
def degister(self):
pass
然后写一下上述接口的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"
check = consul.Check.http(f'{schema}://{service_instance.host}:{service_instance.port}/actuator/health', "10s", "10s", "10s")
// 调用consul的接口来实现服务注册
self._consul.agent.service.register(service_id= service_instance.service_id, address= service_instance.host,
port= service_instance.port, tags= service_instance.tags,
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
所谓服务状态的健康检查接口,指的是consul会定期的请求服务的某个接口,如果该接口有正常的返回,证明该服务还活着。
如果不能正常返回了,则代表该服务下先下线了。consul会将该服务标记为不可用,并且在一定的时候后将其从服务列表中删除。
所以,如果想把服务注册在consul上,需要额外实现一个健康检查的接口,并且将检查地址在注册的时候,以请求参数的形式告知consul,这样consul才能监测服务的状态。。
例如,我们的python服务是基于flask框架构建的,则健康检查接口可以定义为:
from flask import Flask
import json
app = Flask(__name__)
@app.route('/actuator/health')
def service_health():
status = {"status": "UP"}
return json.dumps(status)
启动服务后,再执行一下注册逻辑,就可以发现我们的Python服务成功注册到Consul上去了。
3/服务发现
聊完服务注册,接着实现一下服务发现。
老规矩,先定义服务发现的接口类:
import abc
class DiscoveryClient(abc.ABC):
# 获取注册中心上的服务列表
@abc.abstractment
def get_services(self) -> list:
pass
# 获取某个服务的实例列表
@abc.abstractment
def get_instances(self, service_id: str) -> list:
pass
接着写上述接口类的consul实现
import consul
class ConsulDiscoveryClient(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:
origin_instances_keys = self._consul.catalog.services()[1].keys()
result = []
for origin_instance_key in origin_instance_keys:
result.append(origin_instance_key)
return result
def get_instances(self, service_id: str) -> list:
origin_instances = self._consul.catalog.service(service_id)[1]
result = []
for origin_instance in origin_instances:
result.append(ServiceInstance(
origin_instance.get('ServiceName'),
origin_instance.get('ServiceAddress'),
origin_instance.get('ServicePort'),
origin_instance.get('ServiceTags'),
origin_instance.get('ServiceMeta'),
origin_instance.get('ServiceID'),
))
return result
这样,我们就把python服务注册到consul上了。
照猫画虎,你也可以自行实现如何将Python的Web服务注册到Nacos等其他注册中心。
当然,上面的代码没有考虑线程安全、Https协议等复杂的情形。
读者可自行完善上述代码,使其更加健壮。