Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shut down Akka HTTP app

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?

like image 273
Matthias Braun Avatar asked Apr 21 '17 17:04

Matthias Braun


People also ask

How do you shut down an actor system?

To start the coordinated shutdown process you can either invoke terminate() on the ActorSystem , or run on the CoordinatedShutdown extension and pass it a class implementing CoordinatedShutdown. Reason. for informational purposes: Scala.

What is Akka HTTP?

Akka HTTP is a series of modules that implement a server-side and client-side HTTP stack. It is a general toolkit for providing and consuming HTTP-based services. Any interaction with a browser is part of these modules; however, it is not Akka HTTP's primary concern.

Is Akka HTTP a framework?

It's not a web-framework but rather a more general toolkit for providing and consuming HTTP-based services. While interaction with a browser is of course also in scope it is not the primary focus of Akka HTTP.


1 Answers

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())
like image 83
Matthias Braun Avatar answered Sep 29 '22 12:09

Matthias Braun