Tomcat internal cluster session manager can be used on a test system, but it has performance issue on a production system. (The problem of Tomcat session cluster) From my benchmark test, total TPS saturated from 3 instances. (It depends on H/W spec and business logic)
Therefore I needed to make a custom session manager which saves session data in Redis. The following tips are from my experience.
Download Tomcat source
Core manager implementation
- 2 ways of making a manager is 1) to implement Manager (org.apache.catalina.session.Manager) or 2) to extend ManagerBase (org.apache.catalina.session.ManagerBase)
- Implementing Manager is simple, but extending ManagerBase can reuse some useful logic
- When extending ManagerBase, you must override sessions member attribute (same technique with BackupManager)
- To extend ManagerBase, you need to understand internal Tomcat api (Tomcat javadoc)
- Understanding Tomcat internal component’s lifecycle is crucial to initialize and finalize the custom manager
HttpSession implementation
- Manager handles HttpSession. Therefore you need to make your own HttpSession implementation or extend existing implementation (org.apache.catalina.session.StandardSession)
Custom session manager registeration
Tomcat recoginize custom session manager if <Manager className=”your.custom.manager“> is declared inside <Context>. <Context> can be found at webapp context.xml (file name can be webapp_name.xml at TOMCAT_HOME/conf/Catalina/localhost) (How to define a context)
ClassLoading
- Session manager (including custom manager) is accessed at common loader. (Tomcat classloader hierarchy) Therefore custom manager must be located in CATALINA_HOME/lib or CATALINA_BASE/lib. (Or you can customize it at conf/catalina.properties)
- HttpSession.setAttribute(String, Object) is called at webapp classloader. But session manager is working at common loader. Therefore if the custom manager serializes or deserializes session attribute value object, ClassNotFoundException can occur. To solve the problem, Object serialization/deserialization must use webapp classloader