Wednesday, October 23, 2002 06:32 PM
Excellent question! If you look closely at the output in your logs, it hints at the answer. Notice how every session timed out at exactly*** 4 seconds after the minute.
setMaxInactiveInterval(int) method allows you to specify the timeout interval with a resolution of one second, the servlet specification does not guarantee any specific resolution with which sessions timeouts must occur. Therefore, to improve performance, some servlet containers (Tomcat included) chose to implement session timeouts by having a worker thread wake once per minute and check for expired sessions. In other words, in the case shown, a session is destroyed if the session's timeout period has elapsed by 4 seconds past the minute.
This is (IMHO) a valid performance-enhancing decision because, as you noted, the
web.xml accepts a whole number of minutes for session timeouts. This implies a lifetime on the order of several minutes, meaning sessions need only timeout within +/-1 minute of an exact time. This significantly improves performance over creating a new timer for each session or even checking all sessions once per second--especially as the number of sessions grows. Similarly, Java makes no guarantees that a thread will awaken at any particular time--only that it will sleep for at least the requested interval. As the interval becomes smaller, the "at least" becomes less and less negligible, so the spec/containers generally choose the "no promises made, no promises broken" approach. :)
Note that there is no "magical" number of seconds after the minute at which any specific servlet container will check for expired sessions. Depending on when the servlet container is started, the check could just as easily be performed at 44 seconds after the minute, or 13 seconds after the minute, etc.
***In the case of the last timeout, the message was printed at 5 seconds after the minute. This can be attributed to the fact that nothing is instantaneous in a computer (method calls to the listener objects and output through
System.out take time), and threads are not guaranteed to wake after exactly the requested sleep time. Depending upon what other threads are executing, the thread may not awaken until some time after its sleep period has expired.
Also, I'm sure you realize this (your test class is probably a modified version of an
HttpSessionBindingListener that you already had), but for others reading this post, instead of using an
HttpSessionBindingListener--which is notified when the object is bound to or unbound from an
HttpSession--a more direct method of determining the lifetime of a session would be to implement an
HttpSessionListener--which is notified when a session is created or destroyed.