Downtime refers to the unavailability of servers when the new version of an app is installed to replace the old one. The idea of Blue/Green deployment is to deploy the new version of the app in a separate place where you can test it until you decide to switch to make the new version the main one.
In this article, we will learn how to set up Blue-Green deployment of a Spring boot application. We will use Nginx as the main webserver to redirect incoming requests to our apps.
In this tutorial, we will assume that you have a server and working Spring boot application that you can deploy on it.
On the server, go to your home and create two folders: blue
and green
. Then we will need two symbolic links available
and testing
. These links will alternatively point to either the blue or the green folder. For example, if available
points to green
then testing
point to blue
.
mkdir blue
mkdir green
ln -s ./green ./available
ln -s ./blue ./testing
Each folder will contain its own Spring application and Nginx configuration. At some point during the deployment, both apps will be running at the same time (on different ports though) and to swap from the blue app to the green one we will only need to change the Nginx configuration to either the green one or the blue one.
Let’s say we have the domain “springsite.com”. The green Nginx configuration will redirect all calls to springsite.com/api/ to the green
app on the 8080 port and all calls to springsite.com/api-test/ to the blue
app on the 8090 port.
Let’s create these configuration files. Use your favorite command-line editor to add the following content.
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name mysite.com;
location /api {
proxy_pass http://localhost:8090/api;
}
location /api-test {
proxy_pass http://localhost:8080/api;
}
}
include servers/*;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name mysite.com;
location /api {
proxy_pass http://localhost:8080/api;
}
location /api-test {
proxy_pass http://localhost:8090/api;
}
}
include servers/*;
}
The structure of the files should look like the one below:
--root
|--- blue
|--- nginx.conf.blue
|--- app-V2.jar
|--- green
|--- nginx.conf.green
|--- app-V1.jar
|--- available -> ./green
|--- testing -> ./blue
Let’s say we want to deploy a new version to the blue
container, we can test it while the previous version is still available. Once we are happy with the new version we just need to swap the links!
Create a new file called swap.sh
in the folder containing both blue
and green
folders:
touch swap.sh
chmod +x swap.sh
Add this content to the file:
#!/bin/bash
testing_now=$(ls -l ./ | grep testing)
if [[ "$testing_now" == *blue ]]
then
testing="blue"
active="green"
else
testing="green"
active="blue"
fi
#remove current links
rm ./available
rm ./testing
rm -f /etc/nginx/nginx.conf
#create new links with the active/inactive reversed
ln -s ./$inactive ./available
ln -s ./$active ./testing
ln -s /home/ubuntu/spring/$active/nginx.conf /etc/nginx/nginx.conf
#reload the http server
service nginx reload
echo swap completed $active is now available
At this point, we can launch 2 Spring applications on the ports 8090 and 8080 and swap them by running sudo ./swap.sh
.
Thanks to the symbolic links, we know that the main app is always pointed by available
and that the testing app is pointed by testing
. Hence, we should always deploy the new version of the app in the testing
folder using the symbolic link. Assuming we just packaged the app we can upload it with scp
scp -r -i ~/.ssh/MyKeyPair.pem <package name.jar> <user>@<ip>:spring/testing
Setting up Blue-Green deployment on your server will allow you to reduce downtime significantly. This tutorial explained how to deploy new versions of your application based on a single physical server. This principle can be adapted with several physical servers and a load-balancer. However, this would require having twice as many production environments than needed. For very large infrastructure, this is either not possible or extremely costly.
this leads us to the following question: How do big companies manage to release new versions of their applications without downtime? Think of Google or Facebook, which are always available!
Deploying these apps with Blue-Green deployment is not realistic because of the gigantic number of servers needed. Application updates are done progressively by taking out servers, updating them and putting them back in production. Moreover, new versions are progressively released: at the beginning, only a small fraction of the servers will run the new version. Then, if no problems or bugs are detected, a larger number of servers will run the new code. At this point, important metrics about CPU, memory, and query performances are evaluated. If everything is successful then the release is completed and every server around the world will run the new version of the software.
I hope you now understand how to overcome downtime issues thanks to Blue-Green deployment. You should now be able to set up a basic Blue-Green deployment of your Spring application with an NGINX webserver.
As you may have noticed, when we use this solution both old and current versions of your apps run at the same time and are both connected to the database. This can lead to unexpected issues when there is a change in the database structure. This great article https://spring.io/blog/2016/05/31/zero-downtime-deployment-with-a-database shows how to handle this kind of situation.
One last thing which might interest you it that both AWS and Google Cloud Compute offer services to perform Blue-Green deployment out of the box!