关于Tomcat的session共享引起的思考

7 篇文章 0 订阅

起因

由于在部署项目的时候发现,每次部署都要往tomcat的lib加 `jedis.jar,redis-session.jar,commons-pool.jar,而且只能使用tomcat7x的版本来部署。于是想了解一下怎么回事,了解一下tomcat和redis-session的源码。

关于session管理器

tomcat的session通过session管理器产生。内置的session管理器类图结构如下:

在这里插入图片描述

可以看到,tomcat内置的有主要三种session管理器。
StandardManager :默认的session管理器,单机并且重启之后即session即丢失
PersistentManager:提供了session的持久化功能,可以实现重启tomcat之后还保持session。在内部维持了一个Store,决定将session持久化到文件还是数据库。单机。简单配置如下:
<Context docBase="ecm" path="/ecm">
	<Manager className="org.apache.catalina.session.PersistentManager" debug="0" saveOnRestart="true" maxActiveSessions="-1" minIdleSwap="-1" maxIdleSwap="5" maxIdleBackup="3" >
	    <Store className="org.apache.catalina.session.FileStore" directory="/home/sessions/"/>
	</Manager>
</Context>
<!-- 
className:Session的管理类,tomcat将会通过定义的接口来应用该类生成的对象。 
debug:Session管理器的跟踪级别。 
saveOnRestart:(true/false)配置服务重启工程中对session的处理,若为true,则关闭前把有效的session保存,启动后重新载入 
maxActiveSession:活动状态Session的最大数,为-1时则不限制,否则Session Manager将会把超出的Session对象转移到Session Store中。 
minIdleSwap:Session不活动的最短时间,超过该时间,Session Manager 可能会把该Session对象转移到Session Store中,单位为秒。 
maxidleSwap:Session不活动的最长时间,超过该时间,Session Manager 将会把该Session对象转移到Session Store中,该Session将不在内存中。 
maxidleBackup: Session不活动的最长时间,超过该时间,Session Manager 将会把该Session对象备份到Session Store中,但该Session对象依然存在内存中。
当按照我们上面的配置启动Tomcat后,服务器会根据maxIdleBackup的时间,以秒为单位,进行空闲Session的持久化。在配置的目录中,会生成以sessionId为文件名.session的文件
-->

其中Store可换为如下:

<Store calssName="org.apache.catalina.JDBCStore" driverName="com.mysql.jdbc.Driver" 
connectionURL="jdbc:mysql://localhost/session?usename=xxx&password=xxx" 
sessionTable="session" sessionIdCol="session_id" sessionDataCol="session_data" 
sessionValidCol="sessionValid" sessionMaxInactiveCol="maxInactive" 
sessionLastAccessedCol="lastAccess" sessionAppCol="app" checkInterval="60" debug="99" /> 

session表如下

create table sessions
(
    id varchar(100) not null primary key,
    valid char(1) not null,
    maxinactive int not null,
    lastaccess bigint,
    app varchar(100),
    data mediumblob
);
-- http://svn.apache.org/repos/asf/tomcat/archive/tc4.1.x/trunk/container/catalina/docs/JDBCStore-howto.html
ClusterManagerBase:支持cluster功能的session管理器,即支持session复制功能以支持多个tomcat之间同步session。
为什么说session基于cookies

看源码就很明白了,org.apache.catalina.connector.Request类下

protected Session doGetSession(boolean create) {
        ....
        Manager 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);
            }
        }
        ...
    }

manager.findSession(id)为如下。

	protected Map<String, Session> sessions = new ConcurrentHashMap<String, Session>();
	public Session findSession(String id) throws IOException {
        if (id == null) {
            return null;
        }
        return sessions.get(id);
    }

其中requestedSessionId就是从cookie里获取来的。

    protected void parseSessionCookiesId(org.apache.coyote.Request req, Request request) {
    	//如果禁用了cookies,则直接结束(后续步骤通过URL获取)
                Context context = (Context) request.getMappingData().context;
        if (context != null && !context.getServletContext()
                .getEffectiveSessionTrackingModes().contains(
                        SessionTrackingMode.COOKIE)) {
            return;
        }

        Cookies serverCookies = req.getCookies();
        int count = serverCookies.getCookieCount();
        if (count <= 0) {
            return;
        }

        String sessionCookieName = SessionConfig.getSessionCookieName(context);
		//默认的sessionCookieName为 "JSESSIONID"
		
        for (int i = 0; i < count; i++) {
            ServerCookie scookie = serverCookies.getCookie(i);
            if (scookie.getName().equals(sessionCookieName)) {
                // Override anything requested in the URL
                if (!request.isRequestedSessionIdFromCookie()) {
                    // Accept only the first session id cookie
                    convertMB(scookie.getValue());
                    request.setRequestedSessionId
                        (scookie.getValue().toString());
                    request.setRequestedSessionCookie(true);
                    request.setRequestedSessionURL(false);
                    if (log.isDebugEnabled()) {
                        log.debug(" Requested cookie session id is " +
                            request.getRequestedSessionId());
                    }
                } else {
                    if (!request.isRequestedSessionIdValid()) {
                        // Replace the session id until one is valid
                        convertMB(scookie.getValue());
                        request.setRequestedSessionId
                            (scookie.getValue().toString());
                    }
                }
            }
        }

    }

可以很明显的知道session是基于cookie的,即服务器的session是根据客户端带过来的cookie来识别的。

回到正题:回到我们原来的题目上,在使用nginx等做tomcat集群时,如何实现session的共享。

p.s 关于怎么调试tomcat源码,可以查看:
https://blog.csdn.net/xiongyouqiang/article/details/78941077
https://github.com/apache/tomcat/tree/7.0.94

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值