Like many other developers, most of the apps I’ve developed ended up running in Tomcat. This worked out fine for a while, but one of my biggest pain points was with deployment, or redeployment of an updated app. For some reason, at some point or another, I would run into deployment issues. These issues ranged from Tomcat not exploding my WAR file when auto deployment was enabled, or the app not wanting to start, or even OutOfMemory errors during deployment. Often times, restarting Tomcat or even the server was the only solution. If you have a very small set of apps and a very small set of users accessing those apps, that might seem fine, but as time goes on and you add more apps and more users, restarting Tomcat or the server is no longer feasible.
I had been looking into Spring Boot for a little while and finally decided it was time to migrate an app. This was a simple app which had some
@Async tasks. This wasn’t even an app that users would access, but rather it was a stand alone app that read data from a database, created CSV files and FTP’d them. So it was a simple candidate. I won’t go into details about migrating the app, I’ll just say in the end I had a much shorter POM. I used the Spring Boot starter web, jetty, test and actuator dependencies. I didn’t end up using the Spring Data JPA starter because I prefer EclipseLink to Hibernate.
Running your Spring Boot app in production
Now that I had a functional Spring Boot app (no pun intended), it was time to get it running in production. I knew immediately that I couldn’t simply execute my JAR and be done with it. What happens if the process crashes? What happens if the server is rebooted? I want my app to keep running. So I Googled for some solutions and found this Github issue on Spring Boot which lead me to Supervisor. Supervisor is a simple process control system. Installation was as simple as
easy_install supervisor on my linux server. The documentation on Supervisor’s website is very good, so I recommend you read it if you’re having any trouble.
Once I had Supervisor up and running, I modified the configuration file
supervisord.conf which I put in /etc. Mainly, I changed the last line to include external configuration files for any app I would want to run with Supervisor.
My app configuration file is located at
supervisor/conf.d/myapp.conf, relative to the directory where
supervisord.conf is located.
These files are simple key=value configuration files. This configuration file tells Supervisor to run the command listed at the
command key. The
autorestart keys ensure the app starts and restarts automatically. The
startsecs says that the app must run for at least 10 seconds to be considered a successful start, otherwise retry the number of times denoted by
startretries. The final keys setup logging output.
With that file saved, issuing
supervisorctl reload from the command line will force Supervisor to read in that configuration file and know about my app. It should attempt to start it up automatically. If everything was successful, then issuing
supervisorctl without any arguments, or
supervisorctl status will list the apps running along with their status, PID and uptime. A status of
RUNNING means it’s running successfully. While testing this out, I saw another status of
BACKOFF because the value of my command key in the configuration file wasn’t correct.
And that’s pretty much it for getting a Spring Boot app running in production.
At this point, if this app were a web application that users would access, I would setup a server to act as a reverse proxy to my apps. I’ve had good experience setting up Nginx in this manner. You can have multiple instances of your Spring Boot app running and Nginx can load balance between each instance.
I hope this post helps you out :)