美文网首页squbsScala In Action
squbs-3.运行时的生命周期和API

squbs-3.运行时的生命周期和API

作者: 吕亦行 | 来源:发表于2017-01-16 23:41 被阅读47次

    原文地址:Runtime Lifecycle & API

    生命周期是一个真正需要关注的基础。应用程序很少接触或感知到系统的生命周期。系统组件、管理员控制台、应用组建、actors会经过很长一段时间的初始化,并且为了traffic了解系统生命周期,系统必须在可用前完全初始化。后面包括诸如控制器(controller)、缓存加载器(cache loaders)、设备初始化器等等。

    squbs运行时暴露以下生命周期状态:

    • Starting - squbs启动时的状态

    • Initializing - Unicomplex已启动. Services启动中. Cubes启动中. 等待初始化报告.

    • Active - 准备工作和执行服务调用

    • Failed - Cube可能没有启动

    • Stopping - Unicomplex收到GracefulStop消息 停止cube, actor, 和未绑定的service.

    • Stopped - 运行中的squbs已停止. Unicomplex终止. ActorSystem终止.

    生命周期钩子(Hooks)

    大多数的actor不关心他们什么时候启动或者停止。然而,他们可能为同一类actor,在他们达到接收一般trafiic状态前需要初始化。同样的,一些actor同样关心在关闭前被通知到,以允许在发送他们毒药丸(poison pill)之前适当的清理。生命周期的钩子存在就是为了这个原因。

    你可以通过发送ObtainLifecycleEvents(状态: LifecycleState*)Unicomplex()将你actor注册到生命周期事件中。一旦系统的状态改变,你的actor将会接收到生命周期状态。

    你同样可以通过向Unicomplex()发送SystemState来获得当前的系统状态。你将会获得以上其中一种状态的回复。所有的系统状态对象继承自org.squbs.unicomplex.LifecycleState , 并且所有都属于 org.squbs.unicomplex 包,见下列表:

    • case object Starting extends LifecycleState
    • case object Initializing extends LifecycleState
    • case object Active extends LifecycleState
    • case object Failed extends LifecycleState
    • case object Stopping extends LifecycleState
    • case object Stopped extends LifecycleState

    启动钩子(Hooks)

    一个actor希望参与初始化时必须指出,于是在squbs的元数据 META-INF/squbs-meta.conf如下:

    cube-name = org.squbs.bottlecube
    cube-version = "0.0.2"
    squbs-actors = [
      {
        class-name = org.squbs.bottlecube.LyricsDispatcher
        name = lyrics
        with-router = false  # Optional, defaults to false
        init-required = true # 告知squbs我们需要在发送所有已经启动前等待该actor
      }
    

    任何设置init-required为true的actor需要发送一个已完成(报告)消息至cube管理者,即这些well known actor的父actor。这个报告是Try[Option[String]]类型,允许actor报告初始化成功和失败(可能携带异常)。一旦所有的cube成功的初始化完成,运行中的squbs转变至Active 状态。这同样表示每个设置init-required为true的actor提交了初始化成功的报告。如果任何cube报告一个初始化失败的报告,运行中的squbs会以一个Failed状态取而代之。

    关闭钩子(Hooks)

    停止Actors

    特性org.squbs.lifecycle.GracefulStopHelper让用户在他们自己的代码中实现优雅的关闭actor。你可以按如下的方式在你的actor中混合(mix)这个特性(trait):

    scala
    class MyActor extends Actor with GracefulStopHelper {
        ...
    }
    

    这个特性提供了一些帮助方法来支持在squbs框架中优雅的关闭actor

    StopTimeout

    scala
      /**
       * 优雅的关闭actor的超时时间
       * Override it for customized timeout and it will be registered to the reaper
       * Default to 5 seconds
       * @return Duration
       */
      def stopTimeout: FiniteDuration =
        FiniteDuration(config.getMilliseconds("default-stop-timeout"), TimeUnit.MILLISECONDS)
    

    你可以复写这个方法来指出优雅的关闭actor所需要执行的大概时间。一旦actor启动,它将通过 StopTimeout(stopTimeout) 消息将stopTimeout发送至它们的父节点。如果你关心它,你可以在父actor中处理这条信息。

    如果你混合(mix)这个特性在你的actor代码中,你应该在你的receive 方法中接收GracefulStop消息,因为只有在这种情况下你可以勾住你的代码来执行一个优雅的停止(你无法向PoisonPill添加自定义行为)。管理者将仅仅传播 GracefulStop 消息至他们那些混合了GracefulStopHelper特性的子节点。子节点的实现应该在他们的receive块中处理这个消息。

    我们还提供了以下两个默认策略:

      /**
       * Default gracefully stop behavior for leaf level actors
       * (Actors only receive the msg as input and send out a result)
       * towards the `GracefulStop` message
       *
       * Simply stop itself
       */
      protected final def defaultLeafActorStop: Unit = {
        log.debug(s"Stopping self")
        context stop self
      }
    
      /**
       * Default gracefully stop behavior for middle level actors
       * (Actors rely on the results of other actors to finish their tasks)
       * towards the `GracefulStop` message
       *
       * Simply propagate the `GracefulStop` message to all actors
       * that should be stop ahead of this actor
       *
       * If some actors failed to respond to the `GracefulStop` message,
       * It will send `PoisonPill` again
       *
       * After all the actors get terminated it stops itself
       */
      protected final def defaultMidActorStop(dependencies: Iterable[ActorRef],
                                              timeout: FiniteDuration = stopTimeout / 2): Unit = {
    
        def stopDependencies(msg: Any) = {
          Future.sequence(dependencies.map(gracefulStop(_, timeout, msg)))
        }
    
        stopDependencies(GracefulStop).onComplete({
          // all dependencies has been terminated successfully
          // stop self
          case Success(result) => log.debug(s"All dependencies was stopped. Stopping self")
            if (context != null) context stop self
    
          // some dependencies are not terminated in the timeout
          // send them PoisonPill again
          case Failure(e) => log.warning(s"Graceful stop failed with $e in $timeout")
            stopDependencies(PoisonPill).onComplete(_ => {
              // don't care at this time
              if (context != null) context stop self
            })
        })
      }
    

    停止Squbs插件

    通过复写org.squbs.lifecycle.ExtensionLifecycle中的shutdown()方法,你可以添加在扩展关闭中添加个性化的行为。需要指出的是这个方法在所有安装好的扩展中将在actor系统停止后执行。如果任何扩展在关闭的时候抛出了异常,JVM会以-1退出。

    相关文章

      网友评论

        本文标题:squbs-3.运行时的生命周期和API

        本文链接:https://www.haomeiwen.com/subject/lurpbttx.html