`
cectsky
  • 浏览: 44631 次
  • 性别: Icon_minigender_1
  • 来自: 哈尔滨
社区版块
存档分类
最新评论

HttpSession 失效的内部机制

阅读更多

周六在公司加班,研究了下tomcat session失效的原理,直接上code,以后再补齐一些基本concept.

 

starttime = 2012-11-24 2:57pm (好久没update blog 看看写一篇用多久)

 

2种方式注销session

 

(1)主动 invoke Servlet API 

 

/**
     * Invalidates this session then unbinds any objects bound to it.
     * 
     * @exception IllegalStateException
     *                if this method is called on an already invalidated session
     */
public void invalidate();

 

 

说明:这是HttpSession规范中定义的interface, 看note说将一个session注销然后解除其他对象的绑定. 也就是删除掉session object. 它要求throw 一个Exception

 

tomcat中实现是先 check session object 是不是valid的,如果invalid 直接throw IllegalStateException

然后开始处理,如下

 

    /**
     * Perform the internal processing required to invalidate this session,
     * without triggering an exception if the session has already expired.
     *
     * @param notify Should we notify listeners about the demise of
     *  this session?
     */
    public void expire(boolean notify) {

        // Check to see if expire is in progress or has previously been called
        if (expiring || !isValid)
            return;

        synchronized (this) {
            // Check again, now we are inside the sync so this code only runs once
            // Double check locking - expiring and isValid need to be volatile
            if (expiring || !isValid)
                return;

            expiring = true;
            setValid(false);
            manager.remove(this, true);//在管理对象中讲这个session object删除(内部也是map实现的)

            // 此处nofity标示是否在注销session的时候发送Evnet给listener,典型的观察者pattern
            if (notify) {
                fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
            }

            expiring = false;

            // Unbind any objects associated with this session
            String keys[] = keys();
            for (int i = 0; i < keys.length; i++)
                removeAttributeInternal(keys[i], notify);

        }

    }

 

 

Note that:这段代码就是对specification的标准实现 我精简了一些,从code中学习到了一些知识

(1)如何扩展specification

(2)多线程争用,这个invalid其实是存在多线程mutex操作的。如果一个Thread_A将标志修改了,Thread_B一定要及时知道,所以对操作加以synchronized,对信号量如expiring variable采取volatile修饰保证内存可见性

(3)对于notification, 运用经典的观察者pattern

(4)其实tomcat的session实现还用到了外观等其他design pattern.(面试必背设计模式啊,哈哈)

(5)Map的组合应用(这个地球人都知道,我就不说了)

 

(2) timeout 注销

这个timeout最近深有体会,因为项目设计多线程并发,所以不确定因素很多,比如测试ftp connection等,也不能一直让它retrieve啊,哈哈,相信大家比我理解的深刻。

 

web app中大家都会配置timeout, 比如写在code中 或者xml中的session-timeout node里面,下面share下我学习的内部实现

 

容器类ContainerBase开始启动(tomcat定义了一套组件的lifecycle管理的,还没学习完),然后初始化init方法中开始做一些准备,最后会start一个thread来进行timeout check 的工作(this thread is a daemon thread)

具体的逻辑处理看code

 

    /**
     * Execute a periodic task, such as reloading, etc. This method will be
     * invoked inside the classloading context of this container. Unexpected
     * throwables will be caught and logged.
     */
    @Override
    public void backgroundProcess() {
        if (!getState().isAvailable())
            return;

        if (cluster != null) {...}
        if (loader != null)  {...}          
        if (manager != null) {
            manager.backgroundProcess();              
        }
       //下面做一些pipe的信息处理和事件动作,不是重点就不说了
    }

 

 

manager是session的管理对象,此处会调用它的处理逻辑,code如下

 

    /**
     * 此处比较有创意,是说这个Container被框架每调用6次,就会check一次session timeout 6次是默认的数值
     */
    @Override
    public void backgroundProcess() {
        count = (count + 1) % processExpiresFrequency;
        if (count == 0)
            processExpires();
    }

 核心check timeout的逻辑就很简单了,上次access的时间和这次access的时间间隔是否大于我们定义的timeout.

 

学习到的东东:

(1)lifecycle

(2)线程执行方式

(3)模块化分类,code编码等等

 

nowtime=2012-11-24 3:28pm

cost = nowtime - starttime = 31min

 

用了30多分钟,失败,下篇一定要控制在30min-

 

有说的不对的地方请指教, 本文绝对原创,如需转载,注明出处(估计没人看)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics