こちらで基本的な使用方法をまとめた Akka HTTP Scala アプリケーションをデーモン化します。
yum または Oracle のサイトからダウンロードしてインストールします。Akka の動作には Java 8 以降が必要です。
sudo yum install java-1.8.0-openjdk-devel
こちらから最新の commons-daemon-x.x.x-src.tar.gz
をダウンロードして解凍します。
tar zxvf commons-daemon-1.0.15-src.tar.gz
公式サイトの手順にしたがってビルドします。JCVS はサブディレクトリに格納されています。
The sources are located in the src/native/unix subdirectory.
cd commons-daemon-1.0.15-src/src/native/unix/
必要なソフトウェアをインストールしておきます。
sudo yum install autoconf
sudo yum install gcc-c++
ビルドします。
sh support/buildconf.sh
./configure --with-java=/usr/lib/jvm/java-1.8.0
make
sudo mv jsvc /usr/local/bin/
動作確認します。
$ jsvc -help | head
Usage: jsvc [-options] class [args...]
Where options include:
-help | --help | -?
show this help page (implies -nodetach)
-jvm <JVM name>
use a specific Java Virtual Machine. Available JVMs:
'server'
-client
最新のバージョンは The Central Repository で検索してください。
libraryDependencies += "commons-daemon" % "commons-daemon" % "1.0.15"
build.sbt
lazy val root = (project in file(".")).
settings(
name := "myapp",
version := "1.0",
scalaVersion := "2.11.7",
mainClass in assembly := Some("myapp.Main"),
retrieveManaged := true,
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-http-core" % "2.4.2",
"com.typesafe.akka" %% "akka-http-experimental" % "2.4.2",
"ch.qos.logback" % "logback-classic" % "1.1.3",
"org.slf4j" % "slf4j-api" % "1.7.12",
"commons-daemon" % "commons-daemon" % "1.0.15"
)
)
src/main/resources/logback.xml
<configuration>
<property name="LOG_DIR" value="./log" />
<!-- <property name="LOG_DIR" value="/var/log/myapp" /> -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIR}/myapp.log</file>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${LOG_DIR}/myapp.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 90 days' worth of history -->
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="FILE" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
src/main/scala/Main.scala
package myapp
import org.apache.commons.daemon._
import org.slf4j.LoggerFactory
trait ApplicationLifecycle {
def start(): Unit
def stop(): Unit
}
class ApplicationDaemon extends Daemon {
def init(daemonContext: DaemonContext): Unit = {}
val app: ApplicationLifecycle = new Application
def start() = app.start()
def stop() = app.stop()
def destroy() = app.stop()
}
object Main {
def main(args: Array[String]): Unit = {
val logger = LoggerFactory.getLogger("Main")
val app = new ApplicationDaemon
app.start()
logger.info("Press RETURN to stop...")
scala.io.StdIn.readLine()
app.stop()
}
}
src/main/scala/Application.scala
package myapp
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.Http
import scala.concurrent.Future
import org.slf4j.LoggerFactory
class Application extends ApplicationLifecycle {
val logger = LoggerFactory.getLogger("Application")
val applicationName = "myapp"
implicit val system = ActorSystem(s"$applicationName-system")
implicit val materializer = ActorMaterializer()
implicit val ec = system.dispatcher
var started: Boolean = false
var bindingFuture: Future[Http.ServerBinding] = null
def start(): Unit = {
logger.info(s"Starting $applicationName Service")
if (!started) {
val route = path("") {
get {
logger.info("ok")
complete("ok")
}
}
bindingFuture = Http().bindAndHandle(route, "0.0.0.0", 8080)
logger.info("Server online at http://127.0.0.1:8080/")
started = true
}
}
def stop(): Unit = {
logger.info(s"Stopping $applicationName Service")
if (started) {
bindingFuture.flatMap(_.unbind()).onComplete(_ => system.terminate())
started = false
}
}
}
ビルド
$ sbt assembly
実行例
$ java -jar target/scala-2.11/myapp-assembly-1.0.jar
Starting myapp Service
Server online at http://127.0.0.1:8080/
$ curl http://127.0.0.1:8080
ok
$ cat log/myapp.log
2016-03-17 01:14:00,511 INFO [run-main-0] Application [Application.scala:24] Starting myapp Service
2016-03-17 01:14:01,652 INFO [run-main-0] Application [Application.scala:34] Server online at http://127.0.0.1:8080/
2016-03-17 01:14:02,909 INFO [myapp-system-akka.actor.default-dispatcher-5] Application [Application.scala:29] ok