`

Session 机制 ---- 20161212

阅读更多

session是web开发里一个重要的概念,在大多数web应用里session都是被当做现成的东西,拿来就直接用,但是一些复杂的web应用里能拿来用的session已经满足不了实际的需求,当碰到这样的情况时候我们需要更加深入的理解session的机制,本文将梳理下session的相关知识,为设计可替代web容器自带的session机制打个基础。

 

1.1 session的概念

 

在计算机专业术语里:session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册入系统到注销系统之间所经过的时间以及如果需要的话,可能还有一定操作空间。

 

具体到web应用里的session,大家都做过web开发,这里我就先不提出web里session的定义,先和大伙讲下和session相关的技术背景。

 

早期的web应用或者说早期的网站都是一种处理静态资源的网站,功能主要是查看文档,看看图片,而现在的web应用和早期的差别已经很大,互联网的网站更准确的定义应该是互联网软件即网站就是软件,网站所代表的软件和早期软件的定义是不一样的,早期的软件都是在单机环境下运行,而互联网的普及让软件和网络技术融合在一起,这就要求网站所代表的软件应该要有一个对事务处理的记忆功能,事务处理的记忆功能就是我们常说的要有状态。而实现web应用技术的核心http协议是一个无状态的协议,http这种设计也许是历史遗留问题,也许无状态的http是最简单也是最有效的通讯方式,但是当网站成为软件后,状态的保持就是一个很重要的功能。

因此在web应用开发里就出现了保持http链接状态的技术:一个是cookie技术,另一种是session技术。

 

cookie技术是客户端的解决方案(当然随着html5的出现,比cookie更为强劲和安全的技术出现了,但是鉴于html5的普及度不够,就不做本文讨论的内容了),Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。让我们说得更具体一些:当用户使用浏览器访问一个支持Cookie的网站的时候,用户会提供包括用户名在内的个人信息并且提交至服务器;接着,服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不是存放在HTTP响应体(Response Body)中的,而是存放于HTTP响应头(Response Header);当客户端浏览器接收到来自服务器的响应之后,浏览器会将这些信息存放在一个统一的位置,对于Windows操作系统而言,我们可以从: [系统盘]:\Documents and Settings\[用户名]\Cookies目录中找到存储的Cookie;自此,客户端再向服务器发送请求的时候,都会把相应的Cookie再次发回至服务器。而这次,Cookie信息则存放在HTTP请求头(Request Header)了。有了Cookie这样的技术实现,服务器在接收到来自客户端浏览器的请求之后,就能够通过分析存放于请求头的Cookie得到客户端特有的信息,从而动态生成与该客户端相对应的内容。通常,我们可以从很多网站的登录界面中看到“请记住我”这样的选项,如果你勾选了它之后再登录,那么在下一次访问该网站的时候就不需要进行重复而繁琐的登录动作了,而这个功能就是通过Cookie实现的。

 

session技术则是服务端的解决方案,它是通过服务器来保持状态的。由于Session这个词汇包含的语义很多,因此需要在这里明确一下 Session的含义。首先,我们通常都会把Session翻译成会话,因此我们可以把客户端浏览器与服务器之间一系列交互的动作称为一个 Session。从这个语义出发,我们会提到Session持续的时间,会提到在Session过程中进行了什么操作等等;其次,Session指的是服务器端为客户端所开辟的存储空间,在其中保存的信息就是用于保持状态。从这个语义出发,我们则会提到往Session中存放什么内容,如何根据键值从 Session中获取匹配的内容等。要使用Session,第一步当然是创建Session了。那么Session在何时创建呢?当然还是在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同创建Session的方法,而在Java中是通过调用HttpServletRequest的getSession方法(使用true作为参数)创建的。在创建了Session的同时,服务器会为该Session生成唯一的Session id,而这个Session id在随后的请求中会被用来重新获得已经创建的Session;在Session被创建之后,就可以调用Session相关的方法往Session中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有Session id;当客户端再次发送请求的时候,会将这个Session id带上,服务器接受到请求之后就会依据Session id找到相应的Session,从而再次使用之。正式这样一个过程,用户的状态也就得以保持了。

 

由此我们可以得出,session是解决http协议无状态问题的服务端解决方案,它能让客户端和服务端一系列交互动作变成一个完整的事务,能使网站变成一个真正意义上的软件。

 

1.2 cookie与session的关系

cookie和session的方案虽然分别属于客户端和服务端,但是服务端的session的实现对客户端的cookie有依赖关系的,上面我讲到服务端执行session机制时候会生成session的id值,这个id值会发送给客户端,客户端每次请求都会把这个id值放到http请求的头部发送给服务端,而这个id值在客户端会保存下来,保存的容器就是cookie,因此当我们完全禁掉浏览器的cookie的时候,服务端的session也会不能正常使用(注意:有些资料说ASP解决这个问题,当浏览器的cookie被禁掉,服务端的session任然可以正常使用,ASP我没试验过,但是对于网络上很多用php和jsp编写的网站,我发现禁掉cookie,网站的session都无法正常的访问)

 

1.3 session实现的原理

java的web容器都实现了session机制,实现的逻辑思想都是一致的,但是具体方案可能会存在一定差异,这里我以tomcat容器为例,探讨下session实现的机制。

下图是tomcat源码里session实现:

 

 

实现包的路径是:org.apache.catalina.session,tomcat对外提供session调用的接口不在这个实现包里,对外接口是在包javax.servlet.http下的HttpSession,而实现包里的StandardSession是tomcat提供的标准实现,当然对外tomcat不希望用户直接操作StandardSession,而是提供了一个StandardSessionFacade类,tomcat容器里具体操作session的组件是servlet,而servlet操作session是通过StandardSessionFacade进行的,这样就可以防止程序员直接操作StandardSession所带来的安全问题。(StandardSessionFacade使用了设计模式里的Façade(外观)模式,外观模式能让不同逻辑层的组件进行解耦)。

 

实现类里有Manager的类是用来管理session的工具类,它负责创建和销毁session对象,其中ManagerBase是所有session管理工具类的基类,它是一个抽象类,所有具体实现session管理功能的类都要继承这个类,该类有一个受保护的方法,该方法就是创建sessionId值的方法(tomcat的session的id值生成的机制是一个随机数加时间加上jvm的id值,jvm的id值会根据服务器的硬件信息计算得来,因此不同jvm的id值都是唯一的),StandardManager类是tomcat容器里默认的session管理实现类,它会将session的信息存储到web容器所在服务器的内存里。PersistentManagerBase也是继承ManagerBase类,它是所有持久化存储session信息的基类,PersistentManager继承了PersistentManagerBase,但是这个类只是多了一个静态变量和一个getName方法,目前看来意义不大,对于持久化存储session,tomcat还提供了StoreBase的抽象类,它是所有持久化存储session的基类,另外tomcat还给出了文件存储FileStore和数据存储JDBCStore两个实现。

 

1.4 在实际运用中session所带来的问题

由上面所描述的session实现机制,我们会发现,为了弥补http协议的无状态的特点,服务端会占用一定的内存和cpu用来存储和处理session计算的开销,这也就是tomcat这个的web容器的并发连接那么低(tomcat官方文档里默认的连接数是200)原因之一。因此很多java语言编写的网站,在生产环境里web容器之前会加一个静态资源服务器,例如:apache服务器或nginx服务器,静态资源服务器没有解决http无状态问题的功能,因此部署静态资源的服务器也就不会让出内存或cpu计算资源专门去处理像session这样的功能,这些内存和cpu资源可以更有效的处理每个http请求,因此静态资源服务器的并发连接数更高,所以我们可以让那些没有状态保持要求的请求直接在静态服务器里处理,而要进行状态保持的请求则在java的web容器里进行处理,这样能更好的提升网站的效率。

 

当下的互联网网站为了提高网站安全性和并发量,服务端的部署的服务器的数量往往是大于或等于两台,多台服务器对外提供的服务是等价的,但是不同的服务器上面肯定会有不同的web容器,由上面的讲述我们知道session的实现机制都是web容器里内部机制,这就导致一个web容器里所生成的session的id值是不同的,因此当一个请求到了A服务器,浏览器得到响应后,客户端存下的是A服务器上所生成的session的id,当在另一个请求分发到了B服务器,B服务器上的web容器是不能识别这个session的id值,更不会有这个sessionID所对应记录下来的信息,这个时候就需要两个不同web容器之间进行session的同步。Tomcat容器有一个官方的解决方案就是使用apache+tomcat+mod_jk方案,当一个web容器里session的信息发生变化后,该web容器会向另一个web容器进行广播,另一个web收到广播后将session信息同步到自己的容器里,这个过程是十分消耗系统资源,当访问量增加会严重影响到网站的效率和稳定性。

 

我现在所做的网站里有一个解决方案,当用户请求网站的时候会先将请求发送给硬件的负载均衡设备,该设备可以截获客户端发送过来的session的id值,然后我们根据这个id值找到产生这个session的服务器,将请求直接发送给这台服务器。这种解决方案看起来解决了session共享问题,其实结果是将集群系统最终变回了单点系统,如果处理请求的web容器挂掉了,那么用户的相关会话操作也就废掉了。此外,这种做法也干扰了负载均衡服务器的负载均衡的计算,让请求的分发并不是公平的。

 

  一般大型互联公司的网站都是有一个个独立的频道所组成的,例如我们常用的百度,会有百度搜索,百度音乐,百度百科等等,我相信他们不会把这些不同频道都给一个开发团队完成,应该每个频道都是一个独立开发团队,因为每个频道的应用的都是独立的web应用,那么就存在一个跨站点的session同步的问题,跨站点的登录可以使用单点登录的(SSO)的解决方案,但是不管什么解决方案,跨站点的session共享任然是逃避不了的问题。

 

1.5 解决session相关问题的技术方案

由上所述,session一共有两个问题需要解决:

1) session的存储应该独立于web容器,也要独立于部署web容器的服务器;

2)如何进行高效的session同步。

在讲到解决这些问题之前,我们首先要考虑下session如何存储才是高效,是存在内存、文件还是数据库了?文件和数据库的存储方式都是将session的数据固化到硬盘上,操作硬盘的方式就是IO,IO操作的效率是远远低于操作内存的数据,因此文件和数据库存储方式是不可取的,所以将session数据存储到内存是最佳的选择。因此最好的解决方案就是使用分布式缓存技术,例如:memcached和redis,将session信息的存储独立出来也是解决session同步问题的方法。

Tomcat的session同步也有使用memcache的解决方案,大家可以参加下面的文章:

 

  http://blog.sina.com.cn/s/blog_5376c71901017bqx.html

但是该方案只是解决了同步问题,session机制任然和web容器紧耦合,我们需要一个高效、可扩展的解决方案,那么我们就应该不是简单的把session独立出来存储而是设计一个完全独立的session机制,它既能给每个web应用提供session的功能又可以实现session同步,下面是一篇用zookeeper实现的分布式session方案:

http://www.open-open.com/lib/view/open1378556537303.html

 

好了写完了,今天只是简单剖析下session机制,以后有机会我拿出一套最好的独立session设计机制方案来的。

原文链接:http://www.cnblogs.com/sharpxiajun/p/3395607.html

分享到:
评论

相关推荐

    session共享 memcached-session-manager 1.9.6 jar

    标签中的"msn-kryo"是指Kryo序列化库,它是`memcached-session-manager`可选的序列化机制之一。Kryo以其高效的序列化和反序列化速度而闻名,可以显著提升Memcached操作session的速度。而"高性能缓存"则强调了...

    flask-session-cookie-manager-master.zip

    在Flask中,默认的session机制是基于cookies的,这意味着session ID被存储在用户的cookie中。当用户向服务器发送请求时,服务器会根据这个ID查找对应的session数据。然而,这种机制存在一定的风险,如session劫持、...

    tomcat-redis-session-manager-2.0.0.zip

    《Tomcat Redis Session Manager 2.0.0:实现高效且可扩展的Session共享机制》 在现代Web应用中,Session管理是至关重要的一个环节,它用于存储用户的状态信息,如登录状态、购物车等。然而,随着分布式系统的普及...

    tomcat-redis-session-manager-1.2-tomcat-6&7

    在本场景中,它为Redis连接提供了一个池化机制,避免频繁创建和销毁连接,提高性能并减少资源消耗。 "jedis-2.0.0.jar" 是Jedis,一个Java编写的Redis客户端库,它允许Java开发者与Redis服务器进行通信。Jedis提供...

    tomcat-redis-session-manager jar包

    1. **高可用性**:Redis具有主从复制和持久化机制,即使主服务器故障,也能通过从服务器接管,保证服务的连续性。 2. **高性能**:Redis是内存数据库,读写速度极快,对于频繁读取和更新的Session数据,性能显著优于...

    Tomcat8亲测可用 tomcat-redis-session-manager的jar包

    3. **session**:在Web开发中,session是用于跟踪用户状态的一种机制。当用户在网站上进行操作时,服务器会为每个用户创建一个唯一的session ID,并将其存储在客户端(通常是cookie)和服务器端(如内存或数据库)。...

    -redis-session-manager-master.zip

    为了解决这一问题,引入了外部存储机制,如Redis,作为session的持久化存储。 Redis是一个高性能的键值数据库,支持多种数据结构如字符串、哈希、列表、集合、有序集合等,且具备高速读写性能,非常适合用来存储...

    tomcat-redis-session-manager源码

    《深入解析Tomcat-Redis-Session-Manager源码》 在现代Web应用中,服务器端会话管理是一个至关重要的部分,特别是在高并发、分布式环境中。Tomcat作为最流行的Java Servlet容器,提供了丰富的功能来支持这一需求。...

    session-share-libs.rar

    Session是Web服务器用来跟踪用户状态的一种机制。在HTTP协议无状态的特性下,服务器无法识别多次请求是否来自同一个用户。因此,当用户登录后,服务器会为该用户创建一个唯一的Session ID,并将其存储在服务器端。...

    redis-session-manager-redis-session-manager-2.2.0.zip

    在Web应用中,session是服务器端用来跟踪用户状态的重要机制,通常将用户信息如登录状态、购物车数据等存储在session中。而Redis,作为一个高性能的键值存储系统,因其内存存储特性,成为了理想的选择来缓存和管理...

    redis-session-manager-redis-session-manager-2.0.8.zip

    2. **配置**:在Web应用中集成Redis Session Manager需要配置session存储机制,设置Redis服务器的连接参数,如主机名、端口、密码等。 3. **安全性**:由于session数据存储在远程服务器,安全策略需考虑到网络传输...

    redis-session-manager-tomcat6共享包

    这个"redis-session-tomcat6"文件可能是集成Redis session管理的Tomcat 6配置或库文件,用于替换或增强原有的session管理机制。安装和配置这个包可能涉及以下步骤: 1. 下载并添加到Tomcat的lib目录:首先,你需要...

    redis-session-manager-redis-session-manager-2.0.0.tar.gz

    3. **数据持久化**:Redis 提供的数据持久化机制,保证了即使在服务器重启后仍能恢复 session 数据。 4. **自动过期**:可以设置 session 自动过期时间,避免长期占用存储空间。 5. **安全可靠**:通过加密或其它...

    redis-session-manager-redis-session-manager-2.1.1.zip

    在Web开发中,用户会话(Session)是记录用户状态的重要机制,特别是在HTTP协议无状态的特性下。使用Redis作为Session存储有以下几个优势: 1. 高性能:Redis操作是内存级别的,读写速度非常快,适合频繁访问的...

    redis-session-manager-redis-session-manager-2.0.2.zip

    3. **集成到Web应用**:在Web应用的代码中引入Redis Session Manager,替换原有的会话管理机制。 4. **测试**:部署应用后,进行功能测试,确保会话数据能在不同的服务器之间正确同步。 总的来说,Redis Session ...

    redis-session-manager-redis-session-manager-2.0.1.zip

    在Web应用中,session是用于跟踪用户状态的重要机制,当用户登录后,服务器会为该用户创建一个session,将用户的登录信息、购物车等数据存储在服务器端,而不是在客户端的cookie中,这样可以提高安全性并防止数据...

    tomcat-redis-session-manager-master.zip

    通过上述分析,我们可以看到,Tomcat Redis Session Manager提供了便捷的session共享机制,有效地解决了高并发场景下的session管理问题。通过对源码的学习和实践,开发者可以更好地理解和掌握这一技术,提升系统的可...

    commons-pool2-2.0.jar  jedis-2.7.2.jar  tomcat-redis-session-manage-tomcat8.jar

    2.7.2.jar`作为客户端与Redis交互,以及`tomcat-redis-session-manager-tomcat8.jar`作为Tomcat的session管理器,共同实现了高效、可靠的session存储和共享机制。这个方案对于处理高并发和分布式部署的Web应用尤其有...

    tomcat7-redis-session-manager-java6-2.0.0.zip

    Session是服务器端用来跟踪用户状态的一种机制,通常包含用户的登录信息、购物车内容等。在非持久化的情况下,Session信息存储在服务器内存中,但当服务器集群或负载均衡时,这种方法就不再适用。因此,将Session...

    redis-session-manager-redis-session-manager-2.2.1.tar.gz

    Redis Session Manager是一款基于Redis数据库实现的会话管理工具,它主要用在Web应用程序中,用于高效、安全地存储和管理用户的会话数据。这个压缩包文件"redis-session-manager-redis-session-manager-2.2.1.tar.gz...

Global site tag (gtag.js) - Google Analytics