AWS , Spring Boot, Tomcat : Session replication - java

I have a spring boot application which uses embedded tomcat. The app is hosted on multiple EC2 instances, which auto scale if required and some of which may be killed/restarted. So, effectively there are 3 instances of the app running , and requests are routed from the load balancer to any of these instances.
I am trying to track user sessions on my app. I started with implementing container level session management using tomcat HttpSession. But it is not able to track sessions across instances. On researching a bit, I got to know that i need something like session replication.
My app is not running a tomcat cluster, it has 3 independent instances of the API which do not talk to each other in anyway. I am not planning to change that and not sure if it is possible with AWS as it does not encourage multicast communication for this purpose.
Also, I do not want to setup/manage a separate DB (like redis with spring session) just for this purpose, because I only need session Ids for logging, and I need to do that in a lightweight manner.
Is there any other way to manage sessions across instances ? or for my purpose, would it be better to just implement some custom code which can check for session id/token passed to and fro between the frontend and backend.

The goal is to externalize the sessions from your application server so that you can autoscale, restart, load balance etc. without worrying about breaking a User's session.
Honestly on AWS using the Spring stack, I would recommend Spring Session + Redis. I've used it countless times and it is very easy to implement. You can leverage AWS Elasticache which manages the Redis cluster for you (like RDS does for relational DBs).
You could write your own custom implementation of Spring Session with a backing store of S3, Dynamo, etc. But is that really any better than the Redis implementation? I'd recommend the path of least resistance.

Related

Cookie-Based session persistence between pods in kubernetes

Stateless is the way to go for services running in pods however i have been trying to move a stateful app which needs to perform session persistence if one pod goes does for resiliency reasons.
In websphere world IHS can be used to keep track of the session and if a node goes down it can be recreated on the live clone.
Is there an industry standard way to handle this issue without having to refactor the applications code by persisting the session using some sidecar pod ?
Cookie-based sessions are just that, based on cookies. Which are stored by the user's browser, not your app. If you mean a DB-based session with a cookie session ID or similar, then you would need to store things in some kind of central database. I would recommend using an actual database like postgres, but I suppose there is nothing stopping you from using a shared volume :)
Yes. Store the session somewhere. Spring boot supports out of the box MongoDB, Redis, Hazelcast or any JDBC database.
Spring Boot provides Spring Session auto-configuration for a wide
range of data stores. When building a Servlet web application, the
following stores can be auto-configured:
JDBC Redis Hazelcast MongoDB When building a reactive web application,
the following stores can be auto-configured:
Redis MongoDB If a single Spring Session module is present on the
classpath, Spring Boot uses that store implementation automatically.
If you have more than one implementation, you must choose the
StoreType that you wish to use to store the sessions. For instance, to
use JDBC as the back-end store, you can configure your application as
follows:
spring.session.store-type=jdbc
[Tip] You can disable Spring Session by
setting the store-type to none. Each store has specific additional
settings. For instance, it is possible to customize the name of the
table for the JDBC store, as shown in the following example:
spring.session.jdbc.table-name=SESSIONS
For setting the timeout of the
session you can use the spring.session.timeout property. If that
property is not set, the auto-configuration falls back to the value of
server.servlet.session.timeout.

Redis share session with two different web application

I have set up two web applications. they both using spring boot and spring security. these two applications connected to the same redis server.
The first application is used for login with google OAuth. The second application is used for business operation.
These two applications have the same domains but different sub domain.
My purpose is login through the application 1 and store the session in redis then across application 2 by check the session in redis is exist or not.
Is Redis support to share the session between two different we b application? If not, any other methods so that i can achieve my goal?
thanks.
You can use multi web applications connect to Redis server, and write or read data.
So yo can share the session between two different web application.
But I recommended, each Redis should only connected by one Application, and the application can offer many apis for other apps who want to get data.
You can do it easily with help of "spring session". The idea is to configure web application to store session outside server and share it with other application. It supports redis out of the box. Read here for more information,
https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-redis.html#boot-how

Sharing Session between a Spring Boot application and PHP using Redis

We have a lot of pages which are already running in PHP (core) and require very frequent (and sudden) changes. Therefore we would not like to migrate our code base entirely to Java. I was trying to create an architecture where we could have some part of the business logic processing (which requires a stronger foundation) in Spring Boot and the rest (especially the reporting part) to remain in PHP.
Now for this, I want to be able to share the Session between the already existing PHP applications and the application I am currently writing in Spring Boot. I have configured this application to run with Spring Session using Redis. I cannot and do not want to use a table based implementation for session management owing to a limited amount of resources in our database server.
My configuration for using Redis with Spring Spring Boot is as follows:
spring.session.store-type=redis
spring.redis.host=localhost
spring.redis.password=#somepasswordhere
spring.redis.port=6379
server.servlet.session.timeout=20m
spring.session.redis.flush-mode=on_save
spring.session.redis.namespace=SPRING_SESSION
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.max-wait=-1
spring.redis.jedis.pool.min-idle=16
spring.redis.timeout=1s
I have also been able to configure PHP to use the Redis server as it's data store for session management.
I would like to know if there is any way where I can have a common session for the two, i.e. where one application in PHP can access values (and its other properties such as expiry/validity) set to the session by the other application in Spring Boot and vice versa?
Also, I know that it would be off topic, but any suggestions for a more efficient Redis configuration would also be appreciated here for the Spring Session part.

How do I manage login credentials with Spring MVC running on multiple instances

I am getting ready to develop an AWS Spring MVC Web Application that uses Spring login security. I have used it in the past but only with a single instance. I am getting ready to develop a new application that uses AWS Elastic Load Balancing and instance scaling. How does Spring handle login credentials when running on multiple instances? In other words, I log into my web application running on instance-1 and the next session I am making a request on instance-2. How do I handle user credentials between each instance? I am sure this is a common design scenario for Spring MVC Security.
There are two approaches you could explore:
Configure sticky sessions (something that AWS ELB supports) so that all requests for a given session will go to the same instance.
Store session information outside your application, for example in a Redis cache. One clear benefit of this approach is that your application will be better resilient to instance failures, because with sticky sessions all customers tied to a failed instance would have to re-login.

Session Management in microservices

We have the following setup.
STM (Stingrey Traffic Manager) does load balancing + session stickiness
Weblogic 'cluster'
Auth handled by a third party tool
Therefore I do not have to worry about session with regards to horizontal scaling/ running multiple instances of the application. STM/ Weblogic cluster makes sure that the subsequent request come to same managed server.
What we currently have is a monolithic application and we are trying to move to microservices. Also we do not wan't to move out of current infrastructure (i.e. STM/ Weblogic cluster/ Auth tool). What we have planned is:
A Gateway WAR which routes requests to other microservices
N x Microservices (WAR) for each functional sub-domain
Only the API Gateway receives user requests and other microservices are not accessible from outside
So my question is
Should API Gateway be state-full while other microsevices are stateless?
If so, how should the user session data be shared between API Gateway and microservices?
Please suggest any better alternatives and resources/links as well. Thanks.
Let me share my opinion.
First of all, if you can keep your application stateless, by all means do so :)
It will be the best solution in terms of both performance and scalability.
Now, if its impossible, then you should maintain some distributed session management layer.
The gateway responsible for authentication could generate some unique session identifier which could later be used as a key.
This key could be propagated to all the microservices and be a part of the API or something.
In order to access the session, the microservice could 'get' value by key and work with it.
In terms of implementation: I would take a look on NoSQL solutions. Some of them that can suit your need are:
Redis. Take a look on ''hset'' there
Hazelcast. Its more a in-memory grid but if the solution is java only, you can also implement the required functionality
Memcache.d. It will give you an old good map, just distributed :)
There are also other solutions I believe.
Now, the performance is crucial here, otherwise the whole solution will be just too slow. So In my understanding, using an RDBMS would be not be good here, moreover potentially it would be harder to scale it out.
Hope this helps
1)Should API Gateway be state-full while other microservices are stateless?
Yes, As in 12 Factor App guide lines all the services should be stateless.
2)If so, how should the user session data be shared between API Gateway and microservices?
Your API should be stateless therefore do not share the session state to the microservices. The recommended approach is to set up a Redis cache to store session data.

Categories