为什么会立即终止?

zer*_*ing 1 scala akka akka-stream akka-http

我有以下代码,并且想了解为什么在执行时立即停止:

    import akka.actor.ActorSystem
    import akka.http.scaladsl.Http
    import akka.http.scaladsl.model._
    import akka.http.scaladsl.server.Directives._
    import akka.stream.ActorMaterializer
    import scala.io.StdIn

    object WebServer {
      def main(args: Array[String]) {

        implicit val system = ActorSystem("my-system")
        implicit val materializer = ActorMaterializer()
        // needed for the future flatMap/onComplete in the end
        implicit val executionContext = system.dispatcher

        val route =
          path("hello") {
            get {
              complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
            }
          }

        val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
        bindingFuture
          .flatMap(_.unbind()) // trigger unbinding from the port
          .onComplete(_ => system.terminate()) // and shutdown when done
      }
    }
Run Code Online (Sandbox Code Playgroud)

如您所见,它是一个简单的Web应用程序,不应停止运行。
但是,当我删除以下代码时:

bindingFuture
  .flatMap(_.unbind()) // trigger unbinding from the port
  .onComplete(_ => system.terminate()) // and shutdown when done 
Run Code Online (Sandbox Code Playgroud)

然后它将永远运行直到我终止它。
问题是,为什么没有

bindingFuture
  .flatMap(_.unbind()) // trigger unbinding from the port
  .onComplete(_ => system.terminate()) // and shutdown when done 
Run Code Online (Sandbox Code Playgroud)

该应用程序将不会终止?

fra*_*isr 7

bindingFuture在这两种情况下,您都可以完成。如果你坚持

bindingFuture
  .flatMap(_.unbind()) // trigger unbinding from the port
  .onComplete(_ => system.terminate()) // and shutdown when done 
Run Code Online (Sandbox Code Playgroud)

然后unbindterminate在服务器侦听后立即运行,这将导致您的程序立即完成。

如果省略该代码,则程序将继续运行,直到完成所有线程。因为actor系统正在后台运行线程,并且您永远不会终止它,所以这永远不会发生,并且您必须杀死程序才能停止它。

正常关闭任何按键的一种方法是使用它(摘自官方文档

val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
StdIn.readLine() // let it run until user presses return
bindingFuture
  .flatMap(_.unbind()) // trigger unbinding from the port
  .onComplete(_ => system.terminate()) // and shutdown when done
Run Code Online (Sandbox Code Playgroud)

在这种情况下,StdIn.readLine()它将阻塞主线程,直到按下某个键为止,此时将关闭actor系统和http服务器。

如果您要等待自定义的“事件”而不是按键,则可以Future像这样自定义:

// Just build a Future that will get completed when you want to shutdown
// This can be done manually using a `Promise[Unit]`, but you might also be using 
// a library that will give you a Future to wait on.
val myFuture: Future[Unit] = ??? 
myFuture.flatMap(_ => bindingFuture)
    .flatMap(_.unbind())
    .onComplete(_ => system.terminate())
Run Code Online (Sandbox Code Playgroud)