- 浏览: 172344 次
- 性别:
- 来自: 北京
最新评论
-
chainhou:
sunshineman 写道maven 编译不过啊,连不上ec ...
jetty的下载,编译,安装等 -
sunshineman:
maven 编译不过啊,连不上eclipse的proxy
jetty的下载,编译,安装等
最近有个朋友问我:
答:内存中。又问:
答:(当时没看过这块的代码),说由于每个应用对应一个Session管理,此处应该有类似于数组之类的东西,将该应用的session管理起来,当该应用移除或者某些sesion过期时可以准确的删除掉。最近看了下代码,对比下源码,发现回复的还行,没有特别大的出入。
我们的应用中一般都会用到session,那这个session在应用服务器内部到底是怎么保存到处理的呢?
当我们请求一个应用时,如果页面中用到了session,此时的创建session的调用链如下:
以上调用链的部分关键代码:
在setId时,同时在Manager中将相应的session保存了下来。此处对于session的保存使用的是ConcurrentHashMap,在创建后将其添加到map中,session过期后将其移除。
而在停止一个应用时,相应的remove session的调用链如下:
其中执行remove的代码如下:
引用
tomcat的session存在哪里?
答:内存中。又问:
引用
那既然都保存在内存中,要清除过期的sesion时,又怎么能区分是哪个应用的session而不会清除错误?
答:(当时没看过这块的代码),说由于每个应用对应一个Session管理,此处应该有类似于数组之类的东西,将该应用的session管理起来,当该应用移除或者某些sesion过期时可以准确的删除掉。最近看了下代码,对比下源码,发现回复的还行,没有特别大的出入。
我们的应用中一般都会用到session,那这个session在应用服务器内部到底是怎么保存到处理的呢?
当我们请求一个应用时,如果页面中用到了session,此时的创建session的调用链如下:
Daemon Thread [http-bio-8090-exec-1] (Suspended (breakpoint at line 145 in SessionIdGenerator)) owns: SocketWrapper<E> (id=234) SessionIdGenerator.generateSessionId() line: 145 StandardManager(ManagerBase).generateSessionId() line: 807 StandardManager(ManagerBase).createSession(String) line: 653 Request.doGetSession(boolean) line: 2892 Request.getSession(boolean) line: 2315 RequestFacade.getSession(boolean) line: 898 RequestFacade.getSession() line: 910 PageContextImpl._initialize(Servlet, ServletRequest, ServletResponse, String, boolean, int, boolean) line: 146 PageContextImpl.initialize(Servlet, ServletRequest, ServletResponse, String, boolean, int, boolean) line: 125 JspFactoryImpl.internalGetPageContext(Servlet, ServletRequest, ServletResponse, String, boolean, int, boolean) line: 112 JspFactoryImpl.getPageContext(Servlet, ServletRequest, ServletResponse, String, boolean, int, boolean) line: 65 index.jsp line: not available index_jsp(HttpJspBase).service(HttpServletRequest, HttpServletResponse) line: 70 index_jsp(HttpServlet).service(ServletRequest, ServletResponse) line: 728 JspServletWrapper.service(HttpServletRequest, HttpServletResponse, boolean) line: 432 JspServlet.serviceJspFile(HttpServletRequest, HttpServletResponse, String, boolean) line: 390 JspServlet.service(HttpServletRequest, HttpServletResponse) line: 334 JspServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 728 ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 305 ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210 StandardWrapperValve.invoke(Request, Response) line: 222 StandardContextValve.invoke(Request, Response) line: 123 NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 472 StandardHostValve.invoke(Request, Response) line: 171 ErrorReportValve.invoke(Request, Response) line: 99 AccessLogValve.invoke(Request, Response) line: 936 StandardEngineValve.invoke(Request, Response) line: 118 CoyoteAdapter.service(Request, Response) line: 408 Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1009 Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 589 JIoEndpoint$SocketProcessor.run() line: 310 ThreadPoolExecutor$Worker.runTask(Runnable) line: 895 ThreadPoolExecutor$Worker.run() line: 918 TaskThread(Thread).run() line: 662
以上调用链的部分关键代码:
/** * Construct and return a new session object, based on the default * settings specified by this Manager's properties. The session * id specified will be used as the session id. * If a new session cannot be created for any reason, return * <code>null</code>. * * @param sessionId The session id which should be used to create the * new session; if <code>null</code>, a new session id will be * generated * @exception IllegalStateException if a new session cannot be * instantiated for any reason */ @Override public Session createSession(String sessionId) { if ((maxActiveSessions >= 0) && (getActiveSessions() >= maxActiveSessions)) { rejectedSessions++; throw new TooManyActiveSessionsException( sm.getString("managerBase.createSession.ise"), maxActiveSessions); } // Recycle or create a Session instance Session session = createEmptySession(); // Initialize the properties of the new session and return it session.setNew(true); session.setValid(true); session.setCreationTime(System.currentTimeMillis()); session.setMaxInactiveInterval(this.maxInactiveInterval); String id = sessionId; if (id == null) { id = generateSessionId(); //此处生成sessionID } session.setId(id); sessionCounter++; SessionTiming timing = new SessionTiming(session.getCreationTime(), 0); synchronized (sessionCreationTiming) { sessionCreationTiming.add(timing); sessionCreationTiming.poll(); } return (session); } public void setId(String id, boolean notify) { if ((this.id != null) && (manager != null)) manager.remove(this); this.id = id; if (manager != null) manager.add(this); //注意此处 if (notify) { tellNew(); } }
在setId时,同时在Manager中将相应的session保存了下来。此处对于session的保存使用的是ConcurrentHashMap,在创建后将其添加到map中,session过期后将其移除。
/** * Add this Session to the set of active Sessions for this Manager. * * @param session Session to be added */ @Override public void add(Session session) { sessions.put(session.getIdInternal(), session); int size = getActiveSessions(); //此处应该可以使用AtomicInteger替换掉。 if( size > maxActive ) { synchronized(maxActiveUpdateLock) { if( size > maxActive ) { maxActive = size; } } } }
而在停止一个应用时,相应的remove session的调用链如下:
Daemon Thread [http-bio-8090-exec-2] (Suspended (breakpoint at line 733 in ManagerBase)) owns: StandardSession (id=340) owns: StandardManager (id=326) owns: StandardContext (id=327) owns: SocketWrapper<E> (id=341) StandardManager(ManagerBase).remove(Session, boolean) line: 733 StandardSession.expire(boolean) line: 840 StandardManager.doUnload() line: 463 StandardManager.unload() line: 353 StandardManager.stopInternal() line: 518 StandardManager(LifecycleBase).stop() line: 232 StandardContext.stopInternal() line: 5569 StandardContext(LifecycleBase).stop() line: 232 HTMLManagerServlet(ManagerServlet).stop(PrintWriter, ContextName, StringManager) line: 1306 HTMLManagerServlet.stop(ContextName, StringManager) line: 733 HTMLManagerServlet.doPost(HttpServletRequest, HttpServletResponse) line: 221 HTMLManagerServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 647 HTMLManagerServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 728 ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 305 ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210 CsrfPreventionFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 213 ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243 ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210 SetCharacterEncodingFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 108 ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243 ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210 StandardWrapperValve.invoke(Request, Response) line: 222 StandardContextValve.invoke(Request, Response) line: 123 BasicAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 581 StandardHostValve.invoke(Request, Response) line: 171 ErrorReportValve.invoke(Request, Response) line: 99 AccessLogValve.invoke(Request, Response) line: 936 StandardEngineValve.invoke(Request, Response) line: 118 CoyoteAdapter.service(Request, Response) line: 408 Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1009 Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 589 JIoEndpoint$SocketProcessor.run() line: 310 ThreadPoolExecutor$Worker.runTask(Runnable) line: 895 ThreadPoolExecutor$Worker.run() line: 918 TaskThread(Thread).run() line: 662
其中执行remove的代码如下:
/** * 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; if (manager == null) return; ... //省略部分代码 } ... //省略部分代码 if (ACTIVITY_CHECK) { accessCount.set(0); } setValid(false); // Remove this session from our manager's active sessions manager.remove(this, true); } StandardManager中的remove方法: /** * Remove this Session from the active Sessions for this Manager. * * @param session Session to be removed * @param update Should the expiration statistics be updated */ @Override public void remove(Session session, boolean update) { // If the session has expired - as opposed to just being removed from // the manager because it is being persisted - update the expired stats if (update) { long timeNow = System.currentTimeMillis(); int timeAlive = (int) (timeNow - session.getCreationTimeInternal())/1000; updateSessionMaxAliveTime(timeAlive); expiredSessions.incrementAndGet(); SessionTiming timing = new SessionTiming(timeNow, timeAlive); synchronized (sessionExpirationTiming) { sessionExpirationTiming.add(timing); sessionExpirationTiming.poll(); } } if (session.getIdInternal() != null) { sessions.remove(session.getIdInternal()); //注意此处,即为上面保存session的concurrentHashMap } }
发表评论
-
Tomcat官方文档中文版
2017-02-13 17:15 1057在写微信公众号『Tomcat那些事儿』的时候,有不少读者看过 ... -
Cannot add or update a child row: a foreign key constraint fails
2014-03-24 14:49 9675最近在做应用服务器的CTS测试时发现这样一个问题,跑测试用例过 ... -
JAXB annotation说明及其使用
2013-06-14 14:59 3164最近学习REST,,由于jersey的demo中用到了JAXB ... -
获取当前用户所有java进程及jps命令的实现
2013-05-21 17:24 9953我们在开发中经常会遇 ... -
resource-ref与resource-env-ref的区别
2013-01-21 17:28 3419最近工作中处理一个对于资源引用的问题,主要问题是在reso ...
相关推荐
Tomcat_Session的持久化,详细讲解tomcatsession管理的原理和持久化原理
使用SpringSession管理多台tomcat的session同步到redis上
tomcat-redis-session-tomcat tomcat无缝集成redis实现tomcat集群session管理,包含以下jar包:tomcat-redis-session-manager-VERSION.jar jedis-2.5.2.jar commons-pool2-2.2.jar
tomcat8专用session管理包,nginx+redis+tomcat8做负载均衡时要保持会话共享,需要用到的jar包
本资源已通过测试,资源包括所需jar包和配置说明,如果有不明白的可以在本人博客留言。
tomcat-redis-session-tomcat tomcat无缝集成redis实现tomcat集群session管理jar包
主要为大家详细介绍了Tomcat中session的管理机制 ,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
memcached 实现session复制与同步需要的一整套jar
使用tomcat-redis-session-manager进行统一session管理所需jar包,包括tomcat6-jdk6、tomcat7-jdk7、tomcat8-jdk8
上文中在Tomcat的context.xml中配置了Session管理器RedisSessionManager,实现了通过redis来存储session的功能;Tomcat本身提供了多种Session管理器,如下类图: 1.Manager接口类 定义了用来管理session的基本...
通过memcache实现tomcat7的session共享,目前生产环境用的不多了,但自己某个小需求用到,版本冲突好几次,分享给大家,这3个包复制到tomcat的 lib目录下 还有两个包需要 maven引入自己的项目中 <!-- memcache ...
本资源通过Redisson组件实现Tomcat的非黏性会话管理功能,支持多个Tomcat共享存储Session会话信息,支持Tomcat的6.x、7.x、8.x版本,支持JDK1.8+或JDK1.6+环境。Redisson通过重定义Session相关类方法的方式实现...
apache-tomcat-8.0.45以上版本 取消了LifecycleSupport ,而session管理器又不在维护,所有tomcat-8.0.45以上未能实现session同步
redis充当tomcat7 session store需要用到的jar包 使用说明: 1、将zip解压出来的jar包放到tomcat的lib目录下. 2、修改tomcat/conf下的context.xml文件,示例如下: <!-- Default set of monitored resources --> ...
Tomcat7集群扩展session集中管理,tomcat-redis-session-manager使用,所使用jar包和说明
内置: 1、redis安装包 2、单机安装文档 3、集群安装文档 4、tomcat 单机session共享需要的文件和操作文档 5、tomcat 集群session共享需要的文件和操作文档
session 统一存储管理的共享方案。 博客:http://my.oschina.net/ihanfeng/blog/525209 博客已经很详细得说明方案及其代码,如果程序员没有很强的动手能力,那就要付出点代价来下载完整的环境方案。 该方案里面包含...
使用tomcat-redis-session-manager进行统一session管理所需jar包,包括tomcat6-jdk6
tomcat集群session共享 tomcat-redis-session-manager1.2.rar commons-pool2-2.4.2.jar jedis-2.4.2.jar tomcat配置session管理 配置文件context.xml
tomcat7配置session集中存储到redis中所需的jar包,包括content.xml的配置