【发布时间】:2015-04-27 18:51:54
【问题描述】:
我有基于 spray.io 的 web 服务,它作为独立的 jar 运行(我使用 sbt assembly,然后只使用 java -jar myws.jar)。它与喷雾示例中的引导程序几乎相同,如下所示:
/** 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 my-service "$@" & 运行该过程,然后使用kill -9 pid 停止。
我想优雅地停止我的网络服务,这意味着它会完成打开的连接并拒绝新的连接。
github 上的喷雾罐页面推荐to send it an Akka PoisonPill message。理想情况下,我想从命令行启动它,尽可能简单。我想也许可以再附加一个绑定到本地主机的 HTTP 服务器实例,并有一些休息方法停止,也许诊断 web 服务。可行吗?还有什么其他选择?
更新: 我根据答案添加了我可以想象的必须工作的内容,但似乎没有,至少我从未见过我希望在标准输出或日志中看到的任何消息。实际上,我已经尝试了 HttpUnbind、PoisonPill 的变体,一个一个地尝试。有眼光的人可以看看这个吗? 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:所以,它以某种方式起作用,即 - 当 PoisonPill 被发送时,所有当前的 HTTP 连接都关闭了。但我宁愿停止接收新连接,等待 open 返回响应并关闭。
VERDICT:akka 似乎有自己的钩子,因为尽管我的钩子被执行了,但是演员被杀死并且所有连接都在没有我的动作的情况下关闭。如果有人会提供带有 JVM 关闭钩子的解决方案,那就太好了。我认为这是一个重要的问题,很遗憾它在网上没有任何好的食谱。在此期间,我将尝试使用 tcp/http 实现优雅关闭。
【问题讨论】:
-
您可以使用
Http.Unbind消息告诉服务器停止侦听新连接并在超时后关闭打开的连接。见spray.io/documentation/1.2.1/spray-can/http-server/…。有一些休息方法是绝对可能的,请参阅这个喷雾示例(尽管它不会优雅地停止),例如:github.com/spray/spray/blob/master/examples/spray-routing/… -
我到处尝试,但似乎不起作用。请看更新。
-
@jrudolph 我更新了有问题的问题:钩子触发,但是 akka 系统被其他东西(可能是它自己的钩子)关闭,因此进程中的连接被关闭(并且客户端收到错误连接已经由remore关闭)。我希望打开的连接完成,然后才关闭。似乎它与 unbind 本身无关。
-
最终我明白了我的错误在哪里,糟糕的是没有人指出发送
Unbound到IO(Http)本身是没有用的,应该发送给听众。 -
是的,您需要将
Http.Unbind发送给所有侦听器,然后以阻塞方式等待所有侦听器的Unbound响应,而无需从shutdownHook返回,否则该过程将是在清理发生之前关闭。
标签: web-services scala akka spray