Oracle Developers
Published in

Oracle Developers

Run a Tomcat Cluster with Redis session persistence on Oracle Cloud

This blog demonstrates a Clustered Tomcat application on Oracle Application Container Cloud

  • Redis is used as the (HTTP) session store (with Spring Session)
  • Deploy it on Oracle Application Container Cloud using CI/CD feature in Oracle Developer Cloud

We will focus on HTTP Session management (of the app on Tomcat cluster) and its implementation aspects

  • Persistence — using a Redis backed store which can be configured to flush (persist) to disk
  • Stateless — non-sticky session management
  • High Availability— failure of a (application) node does not affect the session data (hence the user) as long as we have at least one node alive
  • Scalability — the application can scale (horizontally or vertically) without affecting user/session data

HTTP Session persistence

Tomcat

It has support (out of the box implementations) for in-memory and persistent HTTP session stores

  • In-memory: Configure Tomcat to use the org.apache.catalina.ha.tcp.SimpleTcpCluster implementation
  • Persistent: Use a file or JDBC store to persist HTTP session info

Tomcat HTTP session store support in Oracle Application Container Cloud

Both in-memory and persistent modes of Tomcat are supported

Solution details

To implement persistent HTTP Session store for clustered Tomcat app, we have a few options at our disposal

  1. Extend Tomcat specific interfaces/classes (e.g org.apache.catalina.session.ManagerBase) or use an existing plugin e.g. Redisson support for Tomcat

2. Build/use a more generic solution — ideally runtime agnostic

Spring Session & Redis combo on Oracle Application Container Cloud

This blog demonstrates option #2. It uses a Redis based implementation of Spring Session

  • Based on theServlet specification — hence container neutral i.e. it can work for any Servlet compliant container (other than Tomcat)
  • A custom Servlet Filter implementation which is responsible for enforcing usage of Spring Session HTTPSession implementation
High level overview

Project is available here — in terms of business logic, it just consists of

  • a simple HTTP Servlet
  • (Spring) configuration class to enable Redis
  • Another utility class to ensure that the Servlet filter kicks in for every HTTP request

Application packaging

We follow the bring-your-own-runtime mantra. The code repository has the following structure

  • the source code (src directory)
  • Tomcat 8.x (tom-accs directory)
  • bootstrap script (start.sh)
#!/bin/bash
if [ -z “$PORT” ];
then
PORT=”8080"
fi
echo “PORT set to $PORT”
# Update server.xml with env vars
sed “s/__PORT__/${PORT}/g” server.template.xml > tom-accs/conf/server.xml
sh tom-accs/bin/catalina.sh run

In addition to the Tomcat startup script invocation, the start.sh script ensures that the server.xml with correct environment variable ($PORT in our case) is generated during application start up

  • templated version of (Tomcat) server.xml (server.xml.template)
  • manifest.json — the mandatory deployment descriptor
{
“runtime”:{“majorVersion”:”8"},
“command”:”sh ./start.sh”,
“notes”:”Tomcat on ACCCS with Redis Session Sharing”
}

Setup

Oracle Developer Cloud

Let’s configure Oracle Developer Cloud for the Continuous Build as well as Deployment process. You can refer to previous blogs for the same (some of the details specific to this example will be highlighted here)

References

Build Job configuration

The build job for this application is generic in nature, but it has some application specific nuances (Build Steps) which will be highlighted in this section

Build Step #1 — Invoke the Maven build to produce the required artifact i.e. a WAR file in this case

Build Step #2 — copy the WAR file into the Tomcat webapps directory and zip everything up (for the final cloud ready artifact)

The end result is a zip file which consists of the binary (WAR file) as well the runtime (Tomcat installation) where its going to execute

Provide Oracle Application Container Cloud (configuration) descriptor

We provide the application (sizing) details as well as Redis co-ordinates (host and port)

Deployment confirmation in Oracle Developer Cloud

Post-deployment status in Application Container Cloud

Test the application

Let’s test the application using cURL and the redis-cli tool

First time access

We will just invoke a HTTP GET on our application URL

curl https://accs-tomcat-redis-<mydomain>.apaas.em2.oraclecloud.com/accs-tomcat-redis-spring/
  • This will create a new HTTP session — highlighted in green
  • Notice the ACCS instance (in green) which processed the request

Add session data & access the application

We will now use the Session ID received above by passing it along with a request which will add some session data — this is a HTTP POST with parameters name and val which are stored in the HTTP session

curl -X POST -H “Cookie: SESSION=09217ecb-6b90–41bf-952f-b41b65070fa2” “https://accs-tomcat-redis-<mydomain>.apaas.em2.oraclecloud.com/accs-tomcat-redis-spring/?name=k1&val=v1"

To access the application, we execute HTTP GET operation as in execute in step #1 (along with Session ID in the header)

Notice that we get back our session data (highlighted in red) which we had added in the previous step

Let’s see our session state in Redis using the redis-cli. Execute aHGETALL command to a Redis Hash (data structure) where the session is stored (the hash name is in a pre-determined format based on the Session ID)

<redis-host>:6379> hgetall spring:session:sessions:09217ecb-6b90–41bf-952f-b41b65070fa2

Notice the Session data (key-value pair k1, v1) which we added in the previous step — it is highlighted in green

Add some more data, access the application & check Redis

Lets rinse and repeat…

curl -X POST -H “Cookie: SESSION=09217ecb-6b90–41bf-952f-b41b65070fa2” “https://accs-tomcat-redis-<my-domain>.apaas.em2.oraclecloud.com/accs-tomcat-redis-spring/?name=abhishek&val=gupta"

In Redis, you will see the newly added session data (highlighted in red)

You (obviously) see the same session data reflected in the application as well — notice the Oracle Application Container Cloud instance names highlighted in red

  • subsequent requests are catered by different instances, but
  • the session data is consistent since its retrieved from the persistent store (Redis)

Scale in & access the application again

Lets reduce the number of instances to 1 — please refer to the documentation for details

  • Session data will be consistent
  • Request will be served by the same Application Container Cloud instance (we just have one now)

Add session data (again)

curl -X POST -H “Cookie: SESSION=09217ecb-6b90–41bf-952f-b41b65070fa2” “https://accs-tomcat-redis-<my-domain>.apaas.em2.oraclecloud.com/accs-tomcat-redis-spring/?name=accs&val=rocks"

Check Redis — you will see the data getting persisted there

Scale out, access the application & check Redis

Lets go back to our 2-instance topology — refer documentation for how to scale out. You will see that

  • On repetitive access, different Application Container Cloud instances will serve the request
  • the application Session data returned will be same as above
  • Redis will also retain the same state

Test the CI/CD flow

Make some code changes and push them to the Developer Cloud service Git repo. This should

  • Automatically trigger the build, which once successful will
  • Automatically trigger the deployment process, and
  • Redeploy the new application version to Application Container Cloud

Recap

All is well that ends well! We were able to configure and implement a stateless, scalable, highly available and persistent HTTP Session management strategy using Redis and Spring Session for a Tomcat web app on Oracle Application Container Cloud

Don’t forget to…

The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

--

--

--

Aggregation of articles from Oracle engineers, Groundbreaker Ambassadors, Oracle ACEs, and Java Champions on all things Oracle technology. The views expressed are those of the authors and not necessarily of Oracle.

Recommended from Medium

Cloudways API: Is It Worth Using in 2022?- Complete Guide

A Fun Project (Pose Detector) With Google’s Teachable Machine

Confirm that the model’s working fine via the preview pane

Selenium test automation tool

The Co-op Close-up: AutoML and Fintech at UMF

File Transfer via Java Sockets

How to get started in AWS Hacking

What’s new on AsyncAPI? Lots!

Learning Python with Interview Questions 4. Move Zeros

image resource: https://unsplash.com/photos/r8dmu2mchQw

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Abhishek Gupta

Abhishek Gupta

Principal Developer Advocate at AWS | I ❤️ Databases, Go, Kubernetes

More from Medium

Deploying Maven package and Docker image to Github Registry using Github Action workflow

Reactor Kafka Driver

Dive into Kubernetes Healthchecks (part 2)

A photograph of multiple doctors at hospital looking down at the patient.

Using Telepresence to intercept microservices on a Kubernetes cluster