2013-03-12 2 views
13

Каким предпочтительным способом является развертывание приложений Scala на удаленном сервере Linux.Развертывание, запуск и остановка приложений Scala на удаленном сервере

Это довольно простой, но ограниченный, способ развертывания приложения Scala на удаленном сервере (хорошо для быстрого тестирования не столь чувствительных проектов):

  1. С удаленного сервера я тяну мой источник из мерзавца
  2. Использование sbt-assembly плагин я построю баночку на сервере
  3. Я затем запустить приложение Scala, используя поЬир, которая позволяет выйти из сеанса удаленного без завершения процесса:

    поЬир ява -jar MyApp.jar> myapp.log 2> myapp.err </DEV/нуль &

Во-первых, что это лучший способ, чтобы остановить этот процесс, когда он работает, принимая во внимание это использование ресурсов таких как базы данных и т. д. Я просто просматриваю идентификатор процесса Java и запускаю его?

Во-вторых, что лучше всего запустить приложение Java автоматически при перезапуске. Я вспоминаю использование init.d в прошлом, но помню, как можно было подняться в гору, поскольку это приложение было Java.

Update:

Я пропустил слон в комнате здесь. Я использую библиотеку Spray, которая, в свою очередь, использует Akka, поэтому предоставляет ряд интересных опций.

+0

Как насчет установки приложения как службы или отправки сообщения о завершении работы через TCP-сокет? –

+0

Что касается вашего первого требования о прекращении процесса в любое время, я рекомендую использовать 'screen' и запускать вашу банку в сеансе экрана. Используйте 'ctrl + a k', чтобы убить окно и процессы, запущенные в нем. – Kane

+0

Спасибо @ Kane. Я забыл об этом. Это классная идея, тем более, что вы можете поделиться экранами с другими разработчиками (если память мне подходит) – Jack

ответ

17

Существует несколько способов кожи кошки ...

Вы может использовать скрипт sbt-start-https://github.com/sbt/sbt-start-script или даже sbt-native-packager https://github.com/sbt/sbt-native-packager

Вы можете вставить пример сценария загрузки Spray в простой ini t.d, который вызывает sbt, как подробно описано в этом ответе https://stackoverflow.com/a/17399574/155689, или просто используйте команду java nohup.

Вы можете создавать классы и скрипты с более высоким демонами или расширять их с помощью скриптов init.d, которые используют Jsvc http://commons.apache.org/proper/commons-daemon/jsvc.html или Java Service Wrapper.http://wrapper.tanukisoftware.com/

Пример демон и приложения класса:

package com.example.myapplication.server 

import akka.actor.{Props, ActorSystem} 
import spray.can.Http 
import akka.io.IO 
import com.example.myapplication.api.MyServiceActor 
import org.apache.commons.daemon._ 

trait ApplicationLifecycle { 
    def start(): Unit 
    def stop(): Unit 
} 

abstract class AbstractApplicationDaemon extends Daemon { 
    def application: ApplicationLifecycle 

    def init(daemonContext: DaemonContext) {} 

    def start() = application.start() 

    def stop() = application.stop() 

    def destroy() = application.stop() 
} 

class ApplicationDaemon() extends AbstractApplicationDaemon { 
    def application = new Application 
} 

object ServiceApplication extends App { 

    val application = createApplication() 

    def createApplication() = new ApplicationDaemon 

    private[this] var cleanupAlreadyRun: Boolean = false 

    def cleanup(){ 
    val previouslyRun = cleanupAlreadyRun 
    cleanupAlreadyRun = true 
    if (!previouslyRun) application.stop() 
    } 

    Runtime.getRuntime.addShutdownHook(new Thread(new Runnable { 
    def run() { 
     cleanup() 
    } 
    })) 

    application.start() 
} 


class Application() extends ApplicationLifecycle with Logging { 

    private[this] var started: Boolean = false 

    private val applicationName = "MyApplication" 

    implicit val actorSystem = ActorSystem(s"$applicationName-system") 

    def start() { 
    logger.info(s"Starting $applicationName Service") 

    if (!started) { 
     started = true 

     val myService = actorSystem.actorOf(Props[MyServiceActor], "my-service") 

     IO(Http) ! Http.Bind(myService, interface = "0.0.0.0", port = 8280) 
    } 
    } 

    def stop() { 
    logger.info(s"Stopping $applicationName Service") 

    if (started) { 
     started = false 
     actorSystem.shutdown() 
    } 
    } 

} 

При развертывании баночки (используйте SBT-узел для жирной банки) в /opt/myapplication/myapplication.jar, добавить некоторые внешние конфигурации в папке /etc/mycompany, то вам можно обернуть, что в /etc/init.d/myapplication сценарии, например, с помощью JSVC:

#!/bin/sh 
### BEGIN INIT INFO 
# Provides:   myapplication 
# Required-Start: $local_fs $remote_fs $network 
# Required-Stop:  $local_fs $remote_fs $network 
# Should-Start:  $named 
# Should-Stop:  $named 
# Default-Start:  2 3 4 5 
# Default-Stop:  0 1 6 
# Short-Description: Control myapplication 
# Description:  Control the myapplication daemon. 
### END INIT INFO 

set -e 

if [ -z "${JAVA_HOME}" ]; then 
     JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:/bin/java::") 
fi 
JAVA_OPTS="-Xms512m -Xmx1024m" 

APP=myapplication 

PID=/var/run/${APP}.pid 
OUT_LOG=/var/log/myapplication/${APP}_out.log 
ERR_LOG=/var/log/myapplication/${APP}_err.log 

DAEMON_USER=yourserviceuser 

APP_LOG_CONFIG=/etc/mycompany/${APP}_logback.xml 
APP_CONFIG=/etc/mycompany/${APP}.conf 
APP_HOME=/opt/${APP} 
APP_CLASSPATH=$APP_HOME/${APP}.jar 
APP_CLASS=com.example.myapplication.server.ApplicationDaemon 

if [ -n "$APP_LOG_CONFIG}" ]; then 
     JAVA_OPTS="-Dlogback.configurationFile=${APP_LOG_CONFIG} ${JAVA_OPTS}" 
fi 

DAEMON_ARGS="-home ${JAVA_HOME} -Dconfig.file=${APP_CONFIG} ${JAVA_OPTS} -pidfile ${PID} -user ${DAEMON_USER} -outfile ${OUT_LOG} -errfile ${ERR_LOG} -cp ${APP_CLASSPATH} ${APP_CLASS}" 

. /lib/lsb/init-functions 

case "$1" in 
     start) 
       log_daemon_msg "Starting ${APP}" 
       cd ${APP_HOME} && jsvc ${DAEMON_ARGS} 
       log_end_msg 0 
       ;; 
     stop) 
       log_daemon_msg "Stopping ${APP}" 
       cd ${APP_HOME} && jsvc -stop ${DAEMON_ARGS} 
       log_end_msg 0 
       ;; 
     *) 
       log_success_msg "Usage: {start|stop}" 
       echo "Usage: {start|stop}" 
       exit 1 
       ;; 
esac 

exit 0 

при этом вы можете теперь sudo service myapplication start|stop

И если как уже упоминалось, что вы хотите, чтобы он автоматически запускается при загрузке системы, то запустите эту команду

sudo update-rc.d myapplication defaults 

Этот демон подход работает с распылителем приложений у меня есть.

+0

Отличный ответ! К сожалению, я не совсем понимаю, что «добавьте некоторые внешние конфигурации в папку/etc/mycompany». Вы имеете в виду jar's и т. Д.? Еще большой ответ. – Jack

+0

Внешние конфигурации являются необязательными и ссылаются на APP_LOG_CONFIG и APP_CONFIG , т. Е. Конфигурацию приложения logback и spray.conf, которая может переопределять конфигурацию внутри вашей баннеры. Но вам нужны ваши build.sbt и Build.scala для прослушивания этих javaoptions. Если они вам не нужны, вы можете упростить свои DAEMON_ARGS и JAVA_OPTS, удалив их ссылку. – flurdy

 Смежные вопросы

  • Нет связанных вопросов^_^