10

I have a running Akka HTTP application and I want to shut it down.

Pressing Ctrl + C in SBT does not work for me (my shell is currently Git Bash for Windows).

What's the recommended way of shutting down an Akka app gracefully?

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171

1 Answers1

10

Taking inspiration from this thread, I added a route to my application that shuts down the application:

def shutdownRoute: Route = path("shutdown") {
  Http().shutdownAllConnectionPools() andThen { case _ => system.terminate() }
  complete("Shutting down app")
}

where system is the app's ActorSystem.

Given this route, I can now shut down my application with

curl http://localhost:5000/shutdown

Edit:

Being able to shut down a server remotely is not a good idea for production code. In the comments, Henrik pointed to a different way that shuts down the server by hitting Enter in the SBT console:

StdIn.readLine()
// Unbind from the port and shut down when done
bindingFuture
  .flatMap(_.unbind())
  .onComplete(_ => system.terminate())

For context, I put the above code at the end of server initialization:

// Gets the host and a port from the configuration
val host = system.settings.config.getString("http.host")
val port = system.settings.config.getInt("http.port")

implicit val materializer = ActorMaterializer()

// bindAndHandle requires an implicit ExecutionContext
implicit val ec = system.dispatcher

import akka.http.scaladsl.server.Directives._
val route = path("hi") {
  complete("How's it going?")
}

// Starts the HTTP server
val bindingFuture: Future[ServerBinding] =
  Http().bindAndHandle(route, host, port)

val log = Logging(system.eventStream, "my-application")

bindingFuture.onComplete {
  case Success(serverBinding) =>
    log.info(s"Server bound to ${serverBinding.localAddress}")

  case Failure(ex) =>
    log.error(ex, "Failed to bind to {}:{}!", host, port)
    system.terminate()
}

log.info("Press enter key to stop...")
// Let the application run until we press the enter key
StdIn.readLine()
// Unbind from the port and shut down when done
bindingFuture
  .flatMap(_.unbind())
  .onComplete(_ => system.terminate())
Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
  • 2
    In this example they show a similar way to exit, using the same method call, but by pressing return instead of opening a connection. May be preferable if you have easy physical access to the machine it's running on. http://doc.akka.io/docs/akka-http/current/scala/http/routing-dsl/index.html#minimal-example – Henrik Apr 22 '17 at 00:22