设为首页 收藏本站
查看: 550|回复: 0

[经验分享] [转]Tomcat(6.0.14) Session创建机制简介

[复制链接]
累计签到:2 天
连续签到:1 天
发表于 2017-2-5 07:13:39 | 显示全部楼层 |阅读模式
  背景:
公司的一个web应用,提交给测试部门做压力测试(由于不是我负责的,不清楚如何做的压力测试,以及测试指标),结果没压多久,就出现OutOfMemory.
接手协助原因查找,通过监控工具,发现StandardSession(org.apache.catalina.session.StandardSession)对象不断增长,毫无疑问,肯定是在不断创建Session对象.
备注:一般做压力测试,每次请求都不会指定JESSESIONID值,导致Web容器认为每次请求都是新的请求,于是创建Session对象.
同事负责代码Review,发现应用没有任何一个地方存放Session内容.困惑之...

问题:Tomcat容器何时创建Session对象?
想当然认为,只有动态存放Session内容的时候,才会创建Session对象.但是事实真得如此吗?

先看Servlet协议描述:
请看:
getSession(booleancreate)方法:
javax.servlet.http.HttpServletRequest.getSession(booleancreate)
ReturnsthecurrentHttpSessionassociatedwiththisrequestor,ififthereisnocurrentsessionandcreateistrue,returnsanewsession.

IfcreateisfalseandtherequesthasnovalidHttpSession,thismethodreturnsnull.

Tomakesurethesessionisproperlymaintained,youmustcallthismethodbeforetheresponseiscommitted.

  
简单地说:当create变量为true时,如果当前Session不存在,创建一个新的Session并且返回.

getSession()方法:
javax.servlet.http.HttpSessiongetSession();
Returnsthecurrentsessionassociatedwiththisrequest,oriftherequestdoesnothaveasession,createsone.

  简单的说:当当前Session不存在,创建并且返回.


所以说,协议规定,在调用getSession方法的时候,就会创建Session对象.



既然协议这么定了,我们再来看看Tomcat是如何实现的:(下面的描述,是基于Tomcat6.0.14版本源码)
先看一张简单的类图:
DSC0000.jpg

ApplicationContext:Servlet规范中ServletContext的实现
StandardContext:Tomcat定义的Context默认实现.维护了一份SessionManager对象,管理Session对象.所有的Session对象都存放在Manager定义的Map<String,Session>容器中.
StanardManager:标准的Session管理,将Session存放在内容,Web容器关闭的时候,持久化到本地文件
PersistentManager:持久化实现的Session管理,默认有两种实现方式:
--持久化到本地文件
--持久化到数据库

了解了大概的概念后,回头再来看看org.apache.catalina.connector.Request.getSession()是如何实现的.
最终调用的是doGetSession(boolean create)方法,请看:
protectedSessiondoGetSession(booleancreate){

//Therecannotbeasessionifnocontexthasbeenassignedyet
if(context==null)
return(null);

//Returnthecurrentsessionifitexistsandisvalid
if((session!=null)&&!session.isValid())
session
=null;
if(session!=null)
return(session);

//Returntherequestedsessionifitexistsandisvalid
Managermanager=null;
if(context!=null)
manager
=context.getManager();
if(manager==null)
return(null);//Sessionsarenotsupported
if(requestedSessionId!=null){
try{
session
=manager.findSession(requestedSessionId);
}
catch(IOExceptione){
session
=null;
}
if((session!=null)&&!session.isValid())
session
=null;
if(session!=null){
session.access();
return(session);
}
}

//Createanewsessionifrequestedandtheresponseisnotcommitted
if(!create)
return(null);
if((context!=null)&&(response!=null)&&
context.getCookies()
&&
response.getResponse().isCommitted()){
thrownewIllegalStateException
(sm.getString(
"coyoteRequest.sessionCreateCommitted"));
}

//Attempttoreusesessionidifonewassubmittedinacookie
//DonotreusethesessionidifitisfromaURL,topreventpossible
//phishingattacks
if(connector.getEmptySessionPath()
&&isRequestedSessionIdFromCookie()){
session
=manager.createSession(getRequestedSessionId());
}
else{
session
=manager.createSession(null);
}

//Creatinganewsessioncookiebasedonthatsession
if((session!=null)&&(getContext()!=null)
&&getContext().getCookies()){
Cookiecookie
=newCookie(Globals.SESSION_COOKIE_NAME,
session.getIdInternal());
configureSessionCookie(cookie);
response.addCookieInternal(cookie,context.getUseHttpOnly());
}

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

}

  

至此,简单地描述了Tomcat Session创建的机制,有兴趣的同学要深入了解,不妨看看Tomcat源码实现.



补充说明,顺便提一下Session的过期策略.
过期方法在:
org.apache.catalina.session.ManagerBase(StandardManager基类) processExpires方法:
publicvoidprocessExpires(){

longtimeNow=System.currentTimeMillis();
Sessionsessions[]
=findSessions();
intexpireHere=0;

if(log.isDebugEnabled())
log.debug(
"Startexpiresessions"+getName()+"at"+timeNow+"sessioncount"+sessions.length);
for(inti=0;i<sessions.length;i++){
if(sessions!=null&&!sessions.isValid()){
expireHere
++;
}
}
longtimeEnd=System.currentTimeMillis();
if(log.isDebugEnabled())
log.debug(
"Endexpiresessions"+getName()+"processingTime"+(timeEnd-timeNow)+"expiredsessions:"+expireHere);
processingTime
+=(timeEnd-timeNow);

}

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


在org.apache.catalina.core.ContainerBase中,会启动一个后台线程,跑一些后台任务,Session过期任务是其中之一:
protectedvoidthreadStart(){

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

threadDone
=false;
StringthreadName
="ContainerBackgroundProcessor["+toString()+"]";
thread
=newThread(newContainerBackgroundProcessor(),threadName);
thread.setDaemon(
true);
thread.start();

}

准确地讲,除非你的应用完全不需要保存状态(无状态应用),不然地话,只要有一个新的连接过来,web容器都需要创建Session概念,维护状态信息.
但是Session是什么?Session仅仅是一个概念:"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."--简单地讲,保存用户状态信息.
所以说,我们完全可以根据应用的需求,定制Session的实现:
a. Session保存到JVM内容中--Tomcat默认的实现
b. Session保存到Cookie中--Cookie-Based Session
c. Session保存到本地文件--Tomcat提供的非默认实现之一
d. Session保存到Cache Store中--比如常见的Memcached
e. Session保存到数据库中--比如保存到mysql数据库session表,中间对于活跃的Session 缓存到cached中.
......
那么,假如一个应用有大量一次性不同用户的请求(仅仅是一次性的,比如上述文章描述的场景),那么选择c,d,e方案都能有效解决文中所描述的问题.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-337545-1-1.html 上篇帖子: 有关JDK,tomcat,android sdk+MyEclipse+adt 配置 下篇帖子: 【性能测试入门】 使用JMeter/Tomcat/Visual VM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表