Demonstration of Blue-Green deployment without breaking sessions, with HAProxy
(See the blog post for a more detailed explanation.)
Use case: Deploy a new version of a webapp so that all new users are sent to the new version while users with open sessions continue using the previous version (so that they don't loose their precious session state). Users of the new version can explicitely ask for the previous version in the case that it doesn't work as expected and vice versa.
Benefits: Get new features to users that need them as soon as possible without affecting anybody negatively and without risking that a defect will prevent users from achieving their goal (thanks to being able to fall back to the previous version).
How to run this?
This PoC has been set up to run via Vagrant.
- Install Vagrant and VirtualBox
haproxy-vm/directory to create and run the Vagrant virtual machine (VM)
vagrant sshto ssh into the VM
- You can now access the PoC webapp via HAProxy via
localhost:8080from your computer and HAProxy's status page via
localhost:8081(inside the VM they are at ports
Notice that Vagrant will mount the
stateless-hello-webapp directory in the VM as
haproxy-vm directory itself is mounted as
Copy the content of
/vagrant/ and the content of
/webapp/ and run
haproxy-vm/provision.sh as root. Access the app at ports
How does it work?
HAProxy runs in front of the instances (versions) of the app (blue and green zones) (1). We always deploy to the "previous" version, thus making the "current" into a new "previous" (2). We inform the apps whether they should accept new users (yes for curent) via a POST request (3) and they communicate it further to HAProxy via its health checks.
- See haproxy's config again, look for
See the HAProxy configuration below
haproxy-vm/files/etc/, it is mostly only copied from
the documentation (sections 4.1, 4.2; only
available for ve. 1.3, there might be better/other ways in newer version).
haproxy-vm/deploy-new-build.sh will build a new binary (unless it exists) and deploy it, switching the current
"current" and "old" zones. (It uses
haproxy-vm/switch-to-server.sh (blue|green|both) to do the actual switch).
- Build date and git hash are recorded during build into the WAR's manifest and displayed at runtime in the "deployment bar"
- The webapp assumes it is the newest version when started but checks its zone against the
current_zonefile if it exists
- ! verify session not lost on prev upon deployment
- Make a (Gatling?) test to verify the sessions stay unbroken while all new requests go to the new instance
- Inject the swtich+version panel via JS to make it easy to include
Nice to have
- Include current Revision/date in the JS pannel - from mvn build to mvn manifest to Java
- What happens if having an old session but prev truly dies? (get 500 or st.)
- Google Analytics for version changes
- Rename health to status => /status/newest-version
- Deploy: verify we can curl the new version (and perhaps that we get the siwtching JS back)