Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Web services 喷雾罐Web服务正常关闭_Web Services_Scala_Akka_Spray - Fatal编程技术网

Web services 喷雾罐Web服务正常关闭

Web services 喷雾罐Web服务正常关闭,web-services,scala,akka,spray,Web Services,Scala,Akka,Spray,我有基于spray.io的Web服务,它作为独立的jar运行(我使用sbt汇编,然后使用java-jar myws.jar)。它的bootsrap与spray示例中的bootsrap非常相似,如下所示: /** Bootstrap */ object Boot extends App { // we need an ActorSystem to host our application in implicit val system = ActorSystem("my-system")

我有基于spray.io的Web服务,它作为独立的jar运行(我使用
sbt汇编
,然后使用
java-jar myws.jar
)。它的bootsrap与spray示例中的bootsrap非常相似,如下所示:

/** Bootstrap */
object Boot extends App {
   // we need an ActorSystem to host our application in
   implicit val system = ActorSystem("my-system")

   // create and start our service actor
   val service = system.actorOf(Props[MyServiceActor], "my-ws-service")

   implicit val timeout = Timeout(10.seconds)

   CLIOptionsParser.parse(args, CLIOptionsConfig()) map { config =>
     // start a new HTTP server
     IO(Http) ? Http.Bind(service, interface = config.interface, port = config.port)
   }
}
现在,我只需在后台使用
java-jar我的服务“$@”和
运行该过程,然后使用
kill-9pid
停止

我想优雅地停止我的Web服务,这意味着它完成打开的连接并拒绝新的连接

喷雾罐页面建议
向其发送Akka毒药信息
。理想情况下,我希望从命令行启动它,尽可能简单。我想可能需要再附加一个绑定到本地主机的HTTP服务器实例,并停止一些rest方法,还可能需要诊断Web服务。可行吗?其他的选择是什么

更新: 根据答案,我补充了我能想象到的必须要起作用的东西,但似乎没有,至少我从来没有在stdout或log中看到过我期望看到的任何消息。事实上,我试过HttpUnbind和毒药,一起试过,一个一个试过。任何一个目光敏锐的人可以看看这个吗?PS.钩子本身调用成功,已检查。我发送给jvm的信号是SIGTERM

/* Simple reaper actor */
class Reaper(refs: ActorRef*) extends Actor {
  private val log = Logging(context.system, this)
  val watched = ArrayBuffer(refs: _*)

  refs foreach context.watch

  final def receive = {
    case Terminated(ref) =>
      watched -= ref
      log.info(s"Terminated($ref)")
      println(s"Terminated($ref)")
      if (watched.isEmpty) {
        log.info("Shutting dow the system")
        println("Shutting dow the system")
        system.shutdown()
      }
  }
}


// termination hook to gracefully shutdown the service
Runtime.getRuntime.addShutdownHook(new Thread() {
  override def run() = {
    val reaper = system.actorOf(Props(new Reaper(IO(Http), service)))
    //IO(Http) ? Http.Unbind(5.minutes)
    IO(Http) ! PoisonPill
  }
})
UPDATE2:因此,它以某种方式工作,即-当发送毒药时,所有当前HTTP连接都被关闭。但我宁愿停止接收新的连接,等待open返回响应并关闭


判决:阿克卡似乎有自己的钩子,因为尽管我的钩子被执行了,演员们还是被杀了,所有的联系都在我不采取行动的情况下关闭了。如果有人能提供JVM关闭钩子的解决方案,那就太好了。我认为这是一个重要的问题,非常遗憾的是,网上没有任何好的食谱。同时,我将尝试使用tcp/http实现优雅的关闭。

kill-9
将立即销毁进程。您可以使用SIGTERM(kill-15)在jvm中触发关闭挂钩

Runtime.getRuntime.addShutdownHook(new Thread() {
  def run() = {
    //here you can send PoisonPill
  }
})

当我尝试使用SIGTERM和JVM钩子时,我需要阻止钩子线程退出,直到我的关闭序列完成,我只是不知道如何做(我在akka方面有点经验不足,所以可能错过了一些明显的解决方案)

我最后做的是只将一个HTTP侦听器附加到localhost,该侦听器具有启动关机的方法(同时,它还方便执行其他任务,如获取服务器状态、触发应用程序中的事件等)

这可能是这样的(我怀疑这可能包含不必要的操作,因此欢迎改进):

在引导中

implicit val system = ActorSystem(...)

// create and start external service actor
val service = system.actorOf(Props[MyWebServiceActor], "my-web-service")

// create internal service to manage application
val controlService = system.actorOf(Props[ControlServiceActor], "control-service")

implicit val timeout = Timeout(10.seconds)

// start a new HTTP server for external service (notifying control of HTTP listener)
IO(Http).tell(Http.Bind(service, interface = config.interface, port = config.port), controlService)

// start internal server looking at localhost
IO(Http) ? Http.Bind(controlService, interface = "127.0.0.1", port = config.controlPort)
和控制服务本身:

class ControlServiceActor extends Actor with HttpService with ActorLogging {
  def actorRefFactory = context
  implicit val system = context.system

  /* Listener of main service */
  var listener: ActorRef = _

  def receive = {
    // this is reply from IO.Http when HTTP listener is bound
    case Http.Bound(_) =>
      listener = sender()
      context.become(mainContext)
  }

  // http api for graceful stop
  val mainContext = runRoute {
    path("stop") {
      get {
        parameter('timeout.as[Int] ? 60) { timeout =>
          complete {
            // unbind makes listener to reject new connections
            context.become(shuttingDownContext)
            log.warning(s"Stopping application within $timeout seconds...")
            context.watch(listener)
            listener ! Http.Unbind(timeout.seconds)

            "Stopping..."
          }
        }
      }
    }
  }

  // Shutdown sequence
  val shuttingDownContext = ({
    // when unbound HTTP listener not accepting connections
    case Http.Unbound =>
      log.info("Webservice unbound, waiting for active connections to complete")

    // when HTTP listener terminated after unbound it has been processed all requests
    case Terminated(ref) if ref == listener =>
      log.info("Webservice finished, exiting")
      system.shutdown()
  }: Actor.Receive) orElse runRoute(complete("Shutdown in progress"))
}

您可以使用
Http.Unbind
消息通知服务器在超时后停止侦听新连接并关闭打开的连接。看见有一些休息的方法来停止是绝对可能的,看看这个喷雾的例子(虽然它没有优雅地停止)为例:我尝试了这里和那里,但它似乎不起作用。请看一下更新。@jrudolph我在问题中更新了:钩子被激活,但akka系统被其他东西关闭(可能是它自己的钩子),因此进程中的连接被关闭(客户端收到错误消息,连接被remore关闭)。我希望打开的连接完成,并仅在此之后关闭。似乎这与解除绑定无关。最终我明白了我的错误所在,没有人指出将
解除绑定的
发送到
IO(Http)
本身是无用的,应该发送给侦听器。是的,您需要向所有侦听器发送
Http.Unbind
,然后等待所有侦听器以阻塞方式发出
Unbind
响应,而不必从
关闭钩子返回,否则进程将在清理之前关闭。请,您能否详细说明在SIGTERM的情况下,关闭顺序如何?比如说,JVM将运行钩子,它如何知道所需的进程已经完成?类似于所描述的(因为spray基于akka)您可以向spray参与者发送一些消息,并使用
been
来更改行为(停止接收连接)。这一切似乎都没有用,因为在SIGTERM上,所有人都被其他东西杀死了,钩子也没用。或者我做错了什么。这是可行的,但hook必须以某种方式阻止执行,并等待所有必要的步骤完成-例如,一些演员关闭,或者某些序列结束。这件事变得非同小可,我在网上找不到任何有用的东西。我放弃了尝试,继续以公认的答案解决问题。就我个人而言,我希望用SIGTERM实现variant,但是……对于开发环境来说,这是一个不错的解决方案!但对于生产环境,您通常希望在服务器重新启动时(尤其是在需要关闭操作以保持环境的其余部分正常运行的情况下),关闭代码也能正常运行,这是事实,但是我还没有找到更好的解决方案。小的输入错误-这不应该是
//关闭序列
?@dmitry除了
Http之外还会发送一个
毒药丸
。考虑到spray的自述页面上说用
毒药丸关闭它,解除绑定是个好主意@我记得我试过毒丸,它以某种直截了当的方式杀死了演员,关闭了连接,但没有等待完成。