Nameko入门——官方文档学习记录
- 开始编辑时间:2022年5月22日
- 完成撰写时间:2022年5月23日
Nameko入门
1. Nameko介绍
A microservices framework for Python that lets service developers concentrate on application logic and encourages testability.
一种python的微服务架构,让服务开发者专注于应用逻辑,并鼓励可测试性。
2. 开发环境
- Ubuntu 18.04 LTS
- python 3.6.9
3. Nameko安装
-
安装rabbitmq(因Nameko使用了RabiitMQ内建的AMQP RPC特性)
sudo apt-get install rabbitmq-server
-
安装nameko
pip install nameko
4. Nameko手册
4.1. Nameko特性
内建特性:
- RPC over AMQP(远程程序调用)
- 异步事件(pub-sub)
- 简单的HTTP GET和POST
- Websocket RPC和订阅(实验性的)
可以直接响应RPC信息,在特定操作时发送事件和侦听其它服务的事件。同时为支持AMQP的客户端提供HTTP接口,为Javascript客户端提供websocket接口。
Nameko鼓励”依赖关系注入模式”,这使编译和测试服务变得简洁。
4.2. 关键概念
4.2.1. 服务解析
一个Nameko服务就是一个python类。该类将应用逻辑压缩在类方法(Method)中,并将所有以来声明为属性。
方法通过特殊的入口装饰暴露给外部。如下代码所示(@rpc)
from nameko.rpc import rpc, RpcProxy
class Service:
name = "service"
# we depend on the RPC interface of "another_service"
other_rpc = RpcProxy("another_service")
@rpc # `method` is exposed over RPC
def method(self):
# application logic goes here
pass
- Entrypoints 入口
入口是它们装饰的服务方法的网关,通常监控外部的实体,如消息队列。在相关事件上,入口可能“触发”,其所装饰的方法将在工作线程上执行。
- 依赖
依赖关系是隐藏不属于核心服务逻辑的代码的机会。将其它服务作为依赖项实现,声明一个依赖,将其作为服务代码与其它所有内容之间的网关。
- 工作线程
当一个入口触发时,工作线程将创建。一个工作线程就是服务类的一个实例,但该实例依赖项的声明替换为这些依赖项的实例。
4.2.2. 依赖注入
向一个服务添加依赖是声明式的。类的属性是一个声明,而不是工作线程能够实际上使用的接口。
类的属性式一个DependencyProvider. 依赖关系提供一个*get_denpendency()*方法,将其结果注入到新创建的工作线程中。
工作线程的生命周期:
- 入口触发
- 工作线程实例化
- 依赖注入到工作线程
- 方法执行
- 工作线程销毁
worker = Service()
worker.other_rpc = worker.other_rpc.get_dependency()
worker.method()
del worker
4.2.3. 并发性
Nameko 构建在 eventlet 库之上,该库通过“greenthreads”提供并发。并发模型是具有隐式 yield 的协同例程。每个工作线程都在自己的绿色线程中执行。可以根据每个工作线程等待 I/O 所花费的时间来调整并发工作线程的最大数量。
许多使用套接字且通常被视为线程安全的 C 扩展可能不适用于“greenthreads”。其中包括librabbitmq,MySQLdb等。
4.2.4. 扩展
所有的入口和依赖提供都将作为扩展生效。这是因为入口和依赖都在服务代码以以外,而且髌骨吧是所有的服务都需要它们。
4.2.5. 运行服务
运行服务所需的只是服务类和相关的配置。运行一个或多个服务最简单的方式是使用Nameko CLI:
nameko run module:[ServiceClass]
这个命令将会在module中查找ServiceClass并执行。
- 服务容器
每一个服务类都被委托给一个ServiceContainer.容器封装服务所需的所有设计功能,并且包含服务类上的所有扩展,实例如下:
from nameko.containers import ServiceContainer
class Service:
name = "service"
# create a container
container = ServiceContainer(Service, config={
})
# ``container.extensions`` exposes all extensions used by the service
service_extensions = list(container.extensions)
# start service
container.start()
# stop service
container.stop()
- 服务执行器 Sevice Runner
ServiceRunner是包含多个容器的封装,对外暴露同时执行和关闭所封装容器的方法。这也是nameko run内部使用的方法。也可以单独执行ServiceRunner中的某一个容器。实例如下:
from nameko.runners import ServiceRunner
from nameko.testing.utils import get_container
class ServiceA:
name = "service_a"
class ServiceB:
name = "service_b"
# create a runner for ServiceA and ServiceB
runner = ServiceRunner(config={
})
runner.add_service(ServiceA)
runner.add_service(ServiceB)
# ``get_container`` will return the container for a particular service
container_a = get_container(runner, ServiceA)
# start both services
runner.start()
# stop both services
runner.stop()
4.3. 命令行接口
4.3.1. 运行一个服务
nameko run <module>[:<ServiceClass>]
搜索并执行一个服务类。这将在前台运行这个服务,知道进程终止。
默认配置参数可通过*–config*进行转换
nameko run --config ./footbar.yaml <modul>[:<ServiceClass>]
一个YMAL配置文件示例如下:
AMQP_URI: 'pyamqp://guest:guest@localhost'
WEB_SERVER_ADDRESS: '0.0.0.0:8000'
rpc_exchange: 'nameko-rpc'
max_workers: 10
parent_calls_tracked: 10
LOGGING:
version: 1
handlers:
console:
class: logging.StreamHandler
root:
level: DEBUG
handlers: [console]
配置的参数值可通过内置的Config接口获取。
4.3.2. 环境变量替换
- YAML配置文件支持了环境变量。可使用Base风格的格式使用:${ENV_VAR}。
- 使用时可提供默认值:${ENV_VAR:default_value}。
- 并提供递归支持: E N V V A R : d e f a u