自定义Extensions

大多数项目都需要自定义一些个性化的功能,而不会是仅靠Nameko提供的内置Extensions就可以完成设计。利用Nameko提供的基础类,可以根据Nameko的设计思路,很方便的将个性化的功能利用Nameko的基础功能类融入到项目中。

在Nameko中能够自定义的内容都是Extensions,包括Dependency Provider和Entrypoint,这两个都是Extension的子类。要自定义一个Extension,一般需要继承nameko.extensions.Extension并且至少定义以下三个方法。

  • .setup(),在Service Container启动之前进行绑定的阶段调用,通常用来进行初始化工作。
  • .start(),在Service Container成功启动之后调用,会在所有的Extension的.setup()完成初始化后调用。
  • .stop(),在Service Container开始关闭之前调用。

Extension的.__init__()方法将在Service Container的.bind()方法执行过程中调用,但Nameko为了避免一些歧义,将Extension的初始化配置改在了.setup()方法中进行。绑定到Service Container中的Extension可以根据Extension类型,通过.entrypoints.dependencies.subextensions三个集合类型属性来进行访问,或者可以直接通过.extensions属性来统一进行访问。

Dependency Provider用于向RPC服务提供一些依赖环境,例如数据库连接、额外的控制功能等。要自定义个一个Dependency Provider一般需要继承nameko.extensions.DependencyProvider并至少实现以下方法。

  • .worker_setup(worker_ctx),在一个Worker执行任务之前调用,这里需要做一些开始任务处理之前的准备工作。在此抛出异常将导致Worker产生失败事件。
  • .worker_result(worker_ctx, result=None, exc_info=None),在一个Worker完成任务获得返回结果后调用,这里需要做一些针对Worker执行结果的处理,或者例如关闭数据库事务会话。
  • .worker_teardown(work_ctx),在一个Worker完成执行一个任务之后调用,这里需要做一些针对工作现场的清理工作,例如提交数据库事务会话。
  • .get_dependency(work_ctx),必须实现的一个方法,这个方法需要返回一个对象,可以是对象或者函数,这个被返回的对象将被注入到Worker中。

自定义Entrypoint一般用来实现新的传输机制或者新的服务初始化机制。要自定义一个Entrypoint,必须完成以下三项内容。

  1. 继承nameko.extensions.Entrypoint类。
  2. 实现.start()方法来启动Entrypoint。如果需要一个后台线程,可以使用Service Container提供的.spawn_managed_thread(function, identifier)来启动。
  3. 调用Service Container的.spawn_worker()方法来启动一个响应。

Entrypoint通常以一个修饰器的形式出现,这可以通过调用.decorator()方法来获取。获取到的修饰器其所接收的所有参数都会用来传递给Entrypoint的.__init__()方法。

在实现Entrypoint必须完成的三项内容中提到了需要使用Service Container的.spawn_worker()方法来启动一个响应,这个方法主要接受以下参数。

  • entrypoint,通常是Entrypoint实例自身。
  • argskwargs,传递给服务方法的参数。
  • context_data=None,一般会初始化为Worker上下文。
  • handle_result=None,一般会指定为Entrypoint中用于处理服务方法返回内容的处理函数。如果指定处理函数,则这个函数必须能够接受以下四个参数,并且必须返回一个元组包括服务方法返回结果和抛出的异常。
    • message,传入的消息。
    • worker_ctx,执行服务方法的Worker上下文。
    • result,服务方法的返回结果。
    • exc_info,服务方法抛出的异常。