Come si esegue un jar eseguibile di avvio primaverile in un ambiente di produzione?


105

Il metodo di distribuzione preferito di Spring Boot è tramite un file jar eseguibile che contiene tomcat al suo interno.

Si inizia con un semplice java -jar myapp.jar.

Ora, voglio distribuire quel jar sul mio server Linux su EC2, mi manca qualcosa o ho davvero bisogno di creare uno script di inizializzazione per avviare correttamente l'applicazione come demone?

Se chiamo semplicemente java -jarl'applicazione muore quando mi disconnetto.

Potrei avviarlo sullo schermo o nohup ma non è molto elegante e un riavvio nel mio server mi costringerebbe ad accedere e avviare il processo manualmente.

Quindi, c'è già qualcosa per il compito in avvio di primavera?


1
nohup / screen (metodo sporco), init / systemd / upstart (metodo corretto)

@RC Sì, questo lo so, come ho già detto, / sbin / init con uno script personalizzato in /etc/init.d, farebbe il lavoro, ma è davvero l'idea che ognuno dovrebbe costruire il proprio script per gestire il daemon (avvio, arresto, riavvio, stato)? Sembra che manchi qualcosa in quella soluzione.
Cleber Goncalves

Sento che manchi qualcosa in spring-boot (è davvero un progetto "fresco" btw) basta contattare il team responsabile e fare una proposta di evoluzione.

Bene, se generi un archivio di guerra puoi usare la versione della tua distribuzione su Tomcat che avrà uno script di inizializzazione pronto per l'uso. D'altra parte, se usi l'approccio jar eseguibile, devi creare il tuo script di inizializzazione personalizzato. Non sono sicuro che sia nel regno di avvio, ma è chiaramente mancante, il che è un po 'strano, quindi chiedo se ho trascurato qualcosa. Li pingerà.
Cleber Goncalves

Risposte:


96

Si noti che a partire da Spring Boot 1.3.0.M1, è possibile creare file jar completamente eseguibili utilizzando Maven e Gradle.

Per Maven, includi semplicemente quanto segue nel tuo pom.xml:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <executable>true</executable>
    </configuration>
</plugin>

Per Gradle aggiungi il seguente snippet al tuo build.gradle:

springBoot {
    executable = true
}

Il jar completamente eseguibile contiene uno script aggiuntivo all'inizio del file, che ti consente di collegare semplicemente il tuo jar di Spring Boot init.do di utilizzare uno systemdscript.

init.d esempio:

$ln -s /var/yourapp/yourapp.jar /etc/init.d/yourapp

Ciò ti consente di avviare, arrestare e riavviare la tua applicazione come:

$/etc/init.d/yourapp start|stop|restart

Oppure usa uno systemdscript:

[Unit]
Description=yourapp
After=syslog.target

[Service]
ExecStart=/var/yourapp/yourapp.jar
User=yourapp
WorkingDirectory=/var/yourapp
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Maggiori informazioni ai seguenti link:


4
Potrebbe anche essere necessario farlo $ chmod +x /etc/init.d/yourappper poter avviare / arrestare / riavviare
Rohith Nandakumar

Devi sempre dare al tuo utente del servizio le autorizzazioni per leggere ed eseguire il file jar. È inoltre necessario configurare il Java predefinito per il server e le variabili di ambiente Java per far funzionare le cose.
micaro

Questo non funziona! L'ho provato e ricevo il seguente errore: Impossibile avviare MyApp.service: Unità MyApp.service non trovata
Martijn Hiemstra

9

Il modo di gran lunga più semplice e affidabile per eseguire le applicazioni Spring Boot in produzione è con Docker. Utilizza Docker Compose, Docker Swarm o Kubernetes se devi utilizzare più servizi connessi.

Ecco un semplice Dockerfiletratto dalla guida ufficiale di Spring Boot Docker per iniziare:

FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD YOUR-APP-NAME.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

Ecco una riga di comando di esempio per eseguire il contenitore come daemon:

docker run \
  -d --restart=always \
  -e "SPRING_PROFILES_ACTIVE=prod" \
  -p 8080:8080 \
  prefix/imagename

3

La mia applicazione Spring Boot ha due inizializzatori. Uno per lo sviluppo e un altro per la produzione. Per lo sviluppo, utilizzo il metodo principale in questo modo:

@SpringBootApplication
public class MyAppInitializer {

    public static void main(String[] args) {
        SpringApplication.run(MyAppInitializer .class, args);
    }

}

Il mio inizializzatore per l'ambiente di produzione estende SpringBootServletInitializer e ha questo aspetto:

@SpringBootApplication
public class MyAppInitializerServlet extends SpringBootServletInitializer{
    private static final Logger log = Logger
            .getLogger(SpringBootServletInitializer.class);
    @Override
    protected SpringApplicationBuilder configure(
            SpringApplicationBuilder builder) {
        log.trace("Initializing the application");
        return builder.sources(MyAppInitializerServlet .class);
    }

}

Io uso gradle e il mio file build.gradle applica il plugin " WAR ". Quando lo eseguo nell'ambiente di sviluppo, utilizzo il task bootrun . Quando, come quando voglio distribuirlo in produzione, utilizzo l' attività di assemblaggio per generare WAR e distribuire.

Posso eseguire come una normale applicazione primaverile in produzione senza scontare i vantaggi forniti dal tomcat integrato durante lo sviluppo. Spero che questo ti aiuti.


2

In un ambiente di produzione, si desidera che l'app venga riavviata al riavvio della macchina, ecc., Creare uno script /etc/init.d/ e collegarsi al runlevel appropriato per avviarlo e arrestarlo è l'approccio corretto. Spring Boot non si estenderà a questo in quanto si tratta di una configurazione specifica del sistema operativo e ci sono tonnellate di altre opzioni, vuoi che funzioni in una jail chroot, ha bisogno di fermarsi / avviare prima di qualche altro software ecc.


2

È possibile utilizzare l'applicazione chiamata Supervisor . Nella configurazione del supervisore è possibile definire più servizi e modi per eseguire lo stesso.

Per le applicazioni Java e Spring boot il comando sarebbe java -jar springbootapp.jar.

È possibile fornire opzioni per mantenere l'applicazione sempre in esecuzione, quindi se EC2 si riavvia, Supervisor riavvierà l'applicazione

Ho trovato Supervisor facile da usare rispetto a mettere gli script di avvio in /etc/init.d/. Gli script di avvio si bloccavano o andavano in stato di attesa in caso di errori.


2

Se stai usando gradle puoi semplicemente aggiungerlo al tuo build.gradle

springBoot {
    executable = true
}

È quindi possibile eseguire l'applicazione digitando ./your-app.jar

Inoltre, puoi trovare una guida completa qui per configurare la tua app come servizio

56.1.1 Installazione come servizio init.d (System V)

http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html

Saluti


In realtà si scopre che dovrebbe essere bootRepackage { executable = true }Vedi docs.spring.io/spring-boot/docs/current/reference/html/…
Philippe

2

Su sistema operativo Windows senza servizio.

start.bat

@ECHO OFF
call run.bat start

stop.bat:

@ECHO OFF
call run.bat stop

run.bat

@ECHO OFF
IF "%1"=="start" (
    ECHO start myapp
    start "myapp" java -jar -Dspring.profiles.active=staging myapp.jar
) ELSE IF "%1"=="stop" (
    ECHO stop myapp
    TASKKILL /FI "WINDOWTITLE eq myapp"
) ELSE (
    ECHO please, use "run.bat start" or "run.bat stop"
)
pause

1

Avvio le applicazioni che voglio eseguire in modo persistente o almeno semipermanente tramite screen -dmS NAME / path / to / script. Per quanto mi risulta questa è la soluzione più elegante.


0

Questo è un semplice plug-in Spring Boot Maven per completare la distribuzione del codice.

la configurazione del plugin come:

<plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <jvmArguments>-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${debug.port}
                    </jvmArguments>
                    <profiles>
                        <profile>test</profile>
                    </profiles>
                    <executable>true</executable>
                </configuration>
            </plugin>

E jvmArtumentssi aggiunge per te jvm. profilessceglierà un profilo per avviare la tua app. executablepuò far funzionare correttamente la tua app.

e se aggiungi mvnwal tuo progetto, o hai un enveriment esperto. Puoi semplicemente chiamare ./mvnw spring-boot:runmvnw o maven mvn spring-boot:run.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.