Tomcat session cluster’s implementation is done by DeltaManager. (There is also BackupManager. I’ll explain it next time)
The class diagram of DeltaManager (based on v8.5.31)
The following is some important characteristics.
- It is enabled by declaring <Manager className=”org.apache.catalina.ha.session.DeltaManager”> inside <Cluster> which is also inside server.xml
- Shares a session data with all the other nodes
- To optimize performance, it sends only delta data. Minimum delta unit is each session’s attribute
- Session replication is done by Tribe, whose role is to manage cluster nodes and send/receive peer to peer data
- Local session data is managed at sessions attribute (which is ManagerBase’s attribute and ConcurrentHashMap type)
- Common local session management logic (put, get, delete) is defined at ManagerBase
- Cluster dependent logic is defind at ClusterManagerBase and DeltaManager
- HttpSession is implemented by DeltaSession which is a child of StandardSession (org.apache.catalina.ha.session.DeltaSession)
How session replication works
Session creation
When a session is created, DeltaManager.createSession() sends the object to all the other nodes
Session update (to change, add or delete attribute)
When an existing session’s attribute value is changed or added (by HttpSession.setAttribute()), DeltaSession records it as delta. When http request is finished, ReplicationValve sends all delta attributes to the other nodes (You must declare ReplicationValve inside server.xml)
Session delete
When a session is deleted, the following call sequence happens.
HttpSession.invalidate() -> StandardSession.invalidate() -> DeltaSession.expire()
Inside DeltaSession.expire(), 1) ManagerBase.remove() is called (local session remove) 2) delete message is sent to all the other nodes
That is, DeltaSession.expire() is the core logic of session delete
Limitations on DeltaManager
- DeltaSession marks an attribute as a delta when HttpSession.setAttribute() is called. Therefore the following source does not work
HttpSession session = request.getSession(false); SomeObject obj = (SomeObject)session.getAttribute("Some attribute"); obj.setAttribte("XXX");
Although SomeObject has been changed, it’s not replicated to the cluster. But in StandardManager (default session manager) the above code works. To sum up, don’t omit calling HttpSession.setAttribute() to replicate session data.
- Session creation and delete is replicated in real time. But session update is replicated when response is sent. Therefore if the same session is accessed concurrently among Tomcat instances, ghost update problem can happen.
- Async servlet does not work perfectly. Session update is broadcasted when ReplicationValve is executed, but it’s execution time is not gueranteed to be after async servlet is finished. So sometimes session update is missing among cluster. (This is not from official document, but from my test and source code analysis)
Next time, I’ll explain BackupManager’s working mechanism.