gpt4 book ai didi

web-services - spray-can webservice 优雅关闭

转载 作者:行者123 更新时间:2023-12-04 04:24:09 26 4
gpt4 key购买 nike

我有基于 spray.io 的网络服务,它作为独立的 jar 运行(我使用 sbt assembly 然后只是 java -jar myws.jar).它与喷雾示例中的 Bootstrap 非常相似,如下所示:

/** 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 上的喷雾 jar 页面建议向它发送 Akka PoisonPill 消息。理想情况下,我想从命令行启动它,尽可能简单。我想也许再附加一个仅绑定(bind)到本地主机的 HTTP 服务器实例,并使用一些其他方法来停止,并可能诊断 Web 服务。可行吗?还有哪些选择?

更新:我根据答案添加了我可以想象必须工作的内容,但似乎没有,至少我从来没有看到我希望在标准输出或日志中看到的任何消息。实际上,我已经尝试过 HttpUnbind、PoisonPill 的变体,以及一个。任何有强硬 akka 眼睛的人都可以看看这个吗?附言。钩子(Hook)本身被成功调用,检查它。我发送给 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 连接都关闭了。但我宁愿停止接收新连接,并等待打开返回响应并关闭。

VERDICT:似乎 akka 有它自己的钩子(Hook),因为尽管我的钩子(Hook)被执行了,但在我没有采取任何行动的情况下,actor 被杀死并且所有连接都关闭了。如果有人会提供带有 JVM 关闭 Hook 的解决方案,那就太好了。我建议这是一个重要的问题,很遗憾它在网上没有任何好的方法。同时,我将尝试使用 tcp/http 实现正常关闭。

最佳答案

虽然我尝试使用 SIGTERM 和 JVM Hook ,但我需要阻止 Hook 线程退出,直到我的关闭序列完成,而我只是不知道该怎么做(我对 akka 有点缺乏经验,所以也许我错过了一些明显的解决方案)。

我最后所做的是仅将另一个 HTTP 监听器附加到 localhost,它具有启动关闭的方法(而且它碰巧对其他任务很方便,例如获取服务器状态、触发应用程序中的事件等)。

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

在 Bootstrap 中:

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"))
}

关于web-services - spray-can webservice 优雅关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24731242/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com