<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    stone2083

    Tomcat(6.0.14) Session創(chuàng)建機(jī)制簡(jiǎn)介

    背景:
    公司的一個(gè)web應(yīng)用,提交給測(cè)試部門(mén)做壓力測(cè)試(由于不是我負(fù)責(zé)的,不清楚如何做的壓力測(cè)試,以及測(cè)試指標(biāo)),結(jié)果沒(méi)壓多久,就出現(xiàn)OutOfMemory.
    接手協(xié)助原因查找,通過(guò)監(jiān)控工具,發(fā)現(xiàn)StandardSession(org.apache.catalina.session.StandardSession)對(duì)象不斷增長(zhǎng),毫無(wú)疑問(wèn),肯定是在不斷創(chuàng)建Session對(duì)象.
    備注:一般做壓力測(cè)試,每次請(qǐng)求都不會(huì)指定JESSESIONID值,導(dǎo)致Web容器認(rèn)為每次請(qǐng)求都是新的請(qǐng)求,于是創(chuàng)建Session對(duì)象.
    同事負(fù)責(zé)代碼Review,發(fā)現(xiàn)應(yīng)用沒(méi)有任何一個(gè)地方存放Session內(nèi)容.困惑之...

    問(wèn)題:Tomcat容器何時(shí)創(chuàng)建Session對(duì)象?
    想當(dāng)然認(rèn)為,只有動(dòng)態(tài)存放Session內(nèi)容的時(shí)候,才會(huì)創(chuàng)建Session對(duì)象.但是事實(shí)真得如此嗎?

    先看Servlet協(xié)議描述:
    請(qǐng)看:
    getSession(boolean create)方法:
    javax.servlet.http.HttpServletRequest.getSession(boolean create)

    Returns the current HttpSession associated with this request or, if if there is no current session and create is true, returns a new session. 

    If create is false and the request has no valid HttpSession, this method returns null. 

    To make sure the session is properly maintained, you must call this method before the response is committed.

    簡(jiǎn)單地說(shuō):當(dāng)create變量為true時(shí),如果當(dāng)前Session不存在,創(chuàng)建一個(gè)新的Session并且返回.

    getSession()方法:
    javax.servlet.http.HttpSession getSession();

    Returns the current session associated with this request, or if the request does not have a session, creates one.
    簡(jiǎn)單的說(shuō):當(dāng)當(dāng)前Session不存在,創(chuàng)建并且返回.


    所以說(shuō),協(xié)議規(guī)定,在調(diào)用getSession方法的時(shí)候,就會(huì)創(chuàng)建Session對(duì)象.



    既然協(xié)議這么定了,我們?cè)賮?lái)看看Tomcat是如何實(shí)現(xiàn)的:(下面的描述,是基于Tomcat6.0.14版本源碼)
    先看一張簡(jiǎn)單的類(lèi)圖:


    ApplicationContext:Servlet規(guī)范中ServletContext的實(shí)現(xiàn)
    StandardContext:Tomcat定義的Context默認(rèn)實(shí)現(xiàn).維護(hù)了一份SessionManager對(duì)象,管理Session對(duì)象.所有的Session對(duì)象都存放在Manager定義的Map<String,Session>容器中.
    StanardManager:標(biāo)準(zhǔn)的Session管理,將Session存放在內(nèi)容,Web容器關(guān)閉的時(shí)候,持久化到本地文件
    PersistentManager:持久化實(shí)現(xiàn)的Session管理,默認(rèn)有兩種實(shí)現(xiàn)方式:
    --持久化到本地文件
    --持久化到數(shù)據(jù)庫(kù)

    了解了大概的概念后,回頭再來(lái)看看org.apache.catalina.connector.Request.getSession()是如何實(shí)現(xiàn)的.
    最終調(diào)用的是doGetSession(boolean create)方法,請(qǐng)看:
    protected Session doGetSession(boolean create) {

            
    // There cannot be a session if no context has been assigned yet
            if (context == null)
                
    return (null);

            
    // Return the current session if it exists and is valid
            if ((session != null&& !session.isValid())
                session 
    = null;
            
    if (session != null)
                
    return (session);

            
    // Return the requested session if it exists and is valid
            Manager manager = null;
            
    if (context != null)
                manager 
    = context.getManager();
            
    if (manager == null)
                
    return (null);      // Sessions are not supported
            if (requestedSessionId != null) {
                
    try {
                    session 
    = manager.findSession(requestedSessionId);
                } 
    catch (IOException e) {
                    session 
    = null;
                }
                
    if ((session != null&& !session.isValid())
                    session 
    = null;
                
    if (session != null) {
                    session.access();
                    
    return (session);
                }
            }

            
    // Create a new session if requested and the response is not committed
            if (!create)
                
    return (null);
            
    if ((context != null&& (response != null&&
                context.getCookies() 
    &&
                response.getResponse().isCommitted()) {
                
    throw new IllegalStateException
                  (sm.getString(
    "coyoteRequest.sessionCreateCommitted"));
            }

            
    // Attempt to reuse session id if one was submitted in a cookie
            
    // Do not reuse the session id if it is from a URL, to prevent possible
            
    // phishing attacks
            if (connector.getEmptySessionPath() 
                    
    && isRequestedSessionIdFromCookie()) {
                session 
    = manager.createSession(getRequestedSessionId());
            } 
    else {
                session 
    = manager.createSession(null);
            }

            
    // Creating a new session cookie based on that session
            if ((session != null&& (getContext() != null)
                   
    && getContext().getCookies()) {
                Cookie cookie 
    = new Cookie(Globals.SESSION_COOKIE_NAME,
                                           session.getIdInternal());
                configureSessionCookie(cookie);
                response.addCookieInternal(cookie, context.getUseHttpOnly());
            }

            
    if (session != null) {
                session.access();
                
    return (session);
            } 
    else {
                
    return (null);
            }

        }


    至此,簡(jiǎn)單地描述了Tomcat Session創(chuàng)建的機(jī)制,有興趣的同學(xué)要深入了解,不妨看看Tomcat源碼實(shí)現(xiàn).



    補(bǔ)充說(shuō)明,順便提一下Session的過(guò)期策略.
    過(guò)期方法在:
    org.apache.catalina.session.ManagerBase(StandardManager基類(lèi)) processExpires方法:
    public void processExpires() {

            
    long timeNow = System.currentTimeMillis();
            Session sessions[] 
    = findSessions();
            
    int expireHere = 0 ;
            
            
    if(log.isDebugEnabled())
                log.debug(
    "Start expire sessions " + getName() + " at " + timeNow + " sessioncount " + sessions.length);
            
    for (int i = 0; i < sessions.length; i++) {
                
    if (sessions[i]!=null && !sessions[i].isValid()) {
                    expireHere
    ++;
                }
            }
            
    long timeEnd = System.currentTimeMillis();
            
    if(log.isDebugEnabled())
                 log.debug(
    "End expire sessions " + getName() + " processingTime " + (timeEnd - timeNow) + " expired sessions: " + expireHere);
            processingTime 
    += ( timeEnd - timeNow );

        }

    其中,Session.isValid()方法會(huì)做Session的清除工作.


    在org.apache.catalina.core.ContainerBase中,會(huì)啟動(dòng)一個(gè)后臺(tái)線程,跑一些后臺(tái)任務(wù),Session過(guò)期任務(wù)是其中之一:
    protected void threadStart() {

            
    if (thread != null)
                
    return;
            
    if (backgroundProcessorDelay <= 0)
                
    return;

            threadDone 
    = false;
            String threadName 
    = "ContainerBackgroundProcessor[" + toString() + "]";
            thread 
    = new Thread(new ContainerBackgroundProcessor(), threadName);
            thread.setDaemon(
    true);
            thread.start();

        }


    OVER :)

    posted on 2010-02-26 16:12 stone2083 閱讀(7067) 評(píng)論(4)  編輯  收藏 所屬分類(lèi): java

    Feedback

    # re: Tomcat(6.0.14) Session創(chuàng)建機(jī)制簡(jiǎn)介 2010-03-05 17:21 小菜花

    也就是說(shuō)session對(duì)象過(guò)多是沒(méi)法規(guī)避的?  回復(fù)  更多評(píng)論   

    # re: Tomcat(6.0.14) Session創(chuàng)建機(jī)制簡(jiǎn)介 2010-03-07 15:30 stone2083

    @小菜花
    準(zhǔn)確地講,除非你的應(yīng)用完全不需要保存狀態(tài)(無(wú)狀態(tài)應(yīng)用),不然地話(huà),只要有一個(gè)新的連接過(guò)來(lái),web容器都需要?jiǎng)?chuàng)建Session概念,維護(hù)狀態(tài)信息.
    但是Session是什么?Session僅僅是一個(gè)概念:"Provides a way to identify a user across more than one page request or visit to a Web site and to store information about that user."--簡(jiǎn)單地講,保存用戶(hù)狀態(tài)信息.
    所以說(shuō),我們完全可以根據(jù)應(yīng)用的需求,定制Session的實(shí)現(xiàn):
    a. Session保存到JVM內(nèi)容中--Tomcat默認(rèn)的實(shí)現(xiàn)
    b. Session保存到Cookie中--Cookie-Based Session
    c. Session保存到本地文件--Tomcat提供的非默認(rèn)實(shí)現(xiàn)之一
    d. Session保存到Cache Store中--比如常見(jiàn)的Memcached
    e. Session保存到數(shù)據(jù)庫(kù)中--比如保存到mysql數(shù)據(jù)庫(kù)session表,中間對(duì)于活躍的Session 緩存到cached中.
    ......
    那么,假如一個(gè)應(yīng)用有大量一次性不同用戶(hù)的請(qǐng)求(僅僅是一次性的,比如上述文章描述的場(chǎng)景),那么選擇c,d,e方案都能有效解決文中所描述的問(wèn)題.  回復(fù)  更多評(píng)論   

    # re: Tomcat(6.0.14) Session創(chuàng)建機(jī)制簡(jiǎn)介 2010-03-07 18:27 小菜花

    @stone2083
    恩,之前我也遇到這個(gè)問(wèn)題,也是性能測(cè)試的時(shí)候發(fā)現(xiàn)內(nèi)存下不來(lái),后來(lái)發(fā)現(xiàn)是session對(duì)象過(guò)多,我們?cè)跍y(cè)試的時(shí)候有傳遞sessionid給服務(wù)器,后來(lái)沒(méi)找到為啥還是有過(guò)多session的原因,后來(lái)不了了之了,因?yàn)榫€上基本上不會(huì)出現(xiàn)這種情況  回復(fù)  更多評(píng)論   

    # re: Tomcat(6.0.14) Session創(chuàng)建機(jī)制簡(jiǎn)介 2010-06-11 20:23 stone2083

    @小菜花
    理論上來(lái)說(shuō),傳遞jsessionid,只要value是一致的,服務(wù)端不會(huì)創(chuàng)建多份session.
    可以在測(cè)試環(huán)境下通過(guò)debug 或者 監(jiān)控工具,跟蹤下創(chuàng)建多份session的情況.  回復(fù)  更多評(píng)論   

    主站蜘蛛池模板: 拍拍拍无挡免费视频网站| a在线视频免费观看| 婷婷亚洲综合一区二区| 国产在线jyzzjyzz免费麻豆 | 99精品全国免费观看视频..| 四虎影视永久免费观看| 国产精品亚洲专区无码WEB| 免费观看的毛片手机视频| 亚洲av日韩精品久久久久久a| 女人让男人免费桶爽30分钟 | 免费视频精品一区二区| 亚洲成A人片在线观看无码3D| 国产精品亚洲а∨无码播放麻豆| 国产拍拍拍无码视频免费| 国产亚洲精AA在线观看SEE| 国产免费无码AV片在线观看不卡| 情人伊人久久综合亚洲| 99re免费在线视频| 亚洲午夜福利精品久久 | 久久99国产乱子伦精品免费| 亚洲综合久久综合激情久久| 成人a毛片视频免费看| 国产精品亚洲αv天堂无码| a级毛片免费观看视频| 亚洲成人福利在线| 拍拍拍无挡视频免费观看1000| 久久久久亚洲精品影视| 日韩一区二区三区免费播放| 最新精品亚洲成a人在线观看| 国产高清不卡免费视频| 亚洲色WWW成人永久网址| 美女视频黄频a免费大全视频| 亚洲无线一二三四区手机| 57pao国产成视频免费播放| 亚洲日本在线电影| 一个人看www在线高清免费看 | 亚洲欧洲无码AV电影在线观看| 麻豆高清免费国产一区| 色噜噜噜噜亚洲第一| 亚洲人成在线电影| 免费无遮挡无码永久在线观看视频|