`

谁在创建session(4)-为什么要关注session的创建

    博客分类:
  • web
阅读更多
    看到有留言,对我如此“执着”的关注session创建很好奇,解释一下吧。

    首先是关注性能,前面提到过session的使用是有代价的,需要在保存在服务器端内容中,每次request.getSeesion()方法获取 session时,实际是在服务器段的一个大的hasp结构中以当前的jsessionid为key,获取对应的value HttpSession对象,这个过程是需要消耗cpu的,当然目前hash算法比较好,这里消耗不那么明显。而一般的应用,消耗的cpu远比这个小开销大出2-3个数量级,因此通常情况不敏感。如果这个session是我们需要使用的,那么付出这些内存和cpu的代码是完全值得的。但是,如果产生大量的没有任何用处的"垃圾session",对大容量,大并发,需要长期稳定运行的系统会带来很无谓的负载。

    注意,我们要讨论是"垃圾session",即是在我们计划外因为某个原因创建,从不使用,完全浪费的session。正常使用的session不在讨论范围内,虽然也有些比较极端的系统号称不使用session来提高服务器性能,有些对性能比较关注的系统/框架则采用其他的方式来避免使用 session,有兴趣的可以google找资料看。

    下面我们来进行一个简单的性能测试,模拟一下比较极端的情况,我在linux下启动resin,只跑两个最简单的jsp文件:

a.jsp不会自动生成session:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page session="false" %>

<!DOCTYPE html PUBLIC "-//W3C/m/DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<%=1%>
</body>
</html>


b.jsp基本相同,但是设置为<%@ page session="true" %>,这个将自动增加
HttpSession session = request.getSesson(true)
语句,我们进行最恶劣的假设,每次请求都生成新的session,看看会是什么情况:

测试工具采用loadrunner,部署在我的笔记本上(dell d620机器,intel 双核 2g内存)。测试比较简单,测试方法和过程忽略(loadrunner的使用也不复杂),只给出结果:

测试中两个场景的运行情况相同:100个线程并发,每次只访问一下a.jsp/b.jsp,运行时间2分钟。使用top命令在服务器段看resin的内存消耗和cpu使用情况,这个只能大概估计,不好准确衡量。

补充:第一次测试时忘了设置resin的<session-max>参数了,后来写了一个sessionLinstener做计数器, resin的默认没有配置session-max,这个时候resin取的值是默认4096,计数器打印日志发现session总数达到4096后,就会 remove掉已经存在的session以保证不超过4096.下面的测试数据时将session-max设置为4096000后测试的结果

测试1:
    a.jsp 不生成session
    resin内存消耗始终是在175-177之间,基本没有变化。cpu基本稳定在19%-22%。
测试2:
    b.jsp 每次生成session
    resin内存消耗从181m逐步增加,到2分钟测试结束时达到283m,大概增加了102M。cpu大体在25%-30%间。

下面可以总结了:
1. 垃圾session会占用内存
    上面只测试了2分钟,考虑通常session的超时时间会是30分钟,这意味着这些占据的内存至少要到30分钟之后resin才能判定超时从resin的session hash结构出移除,之后再被jvm回收。

    创建的session总数为202941,102M内存/202941次请求= 527字节/session,这个数据比较粗糙,但是还是能大体反映问题。一个垃圾session大概要浪费我们0.5k的内存,时间长达30分钟。

2. 垃圾session的调用消耗了cpu资源
    HttpSession session = request.getSesson(true),每次都要new出新的HttpSession对象,然后resin还要给这个HttpSession算出一个jsessionid,再将jsessionid/session以key/value保存到hash结构中。以后resin检查session超时的线程每次检查时都要查看每个垃圾session,看是否超时。

3. 垃圾session增加正常获取session的开销
    前面提到垃圾session也是要保存hash结构中,request.getSesson()每次都要用jsessionid在这个hash结构中取一次数据。当垃圾session大量充斥时,获取当正常有用的session的时间也会增加,具体就要看这个hash结构的算法如何了。

    当前上述的测试都是建立在最苛刻最恶劣的情况下,大多数情况我们的系统不会这么糟糕,也不是每个系统都对访问量/性能有高要求。如果觉得可以浪费的起,那浪费好了,只是我这边系统的情况不同,我们的产品对性能很敏感,能省就省点。

    除考虑性能外, session的创建在我们新设计的系统中,是必须非常严格控制的.这个和我们目前的系统结构,包括部署/用户身份认证有关.简单的说我们的系统是基于 apache + resin的多机分布, 各个功能模块是作为不同的webapp发布的,session的生成和jsessionid的传递必须可控,因此我必须严格掌控系统中session的生成情况。

    另外说一点个人意见,知不知道有这些session自动创建的情况,和决定是否要在自己的代码中严格控制session创建,不是同一个概念。完全可以在了解情况后,根据自己的实际需要和个人习惯去做决定,比如选择无视。但是如果不知道呢?呵呵,很惭愧,在这次探索之前,我对jsp/webwork标签自动生成session是没有概念的,我们的原有系统是不使用HttpSession的(和当时的分布式方案有关),但是现在看来,由于 jsp/webwork标签的存在,其实每次都有session被创建,这些session也就成了我上面说的垃圾session: 在不需要创建时意外创建,从来不使用,除了浪费资源外没有其他存在价值。

    整理一下留言中的内容,感谢大家的关注:
疑问:
    我觉得系统的瓶颈不会出在session生成上 ,花时间在后台缓存和sql优化、架构调整这些事情上来的实惠.
回答:
     滴水的水龙头要不要拧紧的问题?

    没有哪个家庭的财政会因为那个滴水的水龙头造成收支失衡以致破产,那是否就意味着可以无视它的存在,只管专心挣钱,再每个月少吃一次大餐?后台缓存和 sql优化、架构调整,这些当然是更重要的,但不意味着其他东西就可以完全忽略。我无意强调session的这些细节的高度,只是希望告诉大家,在某些角落里,有些我们没有意识到的小水龙头,在一滴一滴的浪费资源。

    后台缓存和sql优化、架构调整,到处可以找到资料。可是我google了一圈,上述session的几个问题根本没有成文的全面一点的资料可以参考,我相信jsp世界中肯定还有很多很多类似的小水龙头在悄悄地滴水,而主人们根本没有看见。

ps: 这个系列的文章最初发在blogjava,现在复制到javaeye(担心哪天某家blog不在了丢失文章),感觉这个话题很少看到有人谈起,我斗胆发到论坛上来看看,是否有人和我持有相同的看法。
分享到:
评论
6 楼 helloint 2008-07-08  
resin下session默认是false
5 楼 wlhok 2008-02-19  
最近需要看session机制,发现这么好的帖子,顶起来!
谢谢楼主的共享
4 楼 skydream 2007-12-30  
ps:lz能不能发到一个帖子里,您早上穿衣服时不喜欢鞋子袜子衣服裤子每个房间去找一样吧。

sorry,这个系列是我陆续整理成文的,当时一篇一篇的陆续发表在blogjava,昨天才整理到javaeye的。

四个帖子的内容太多了,放一个实在太大,而且每个文章的内容都比较独立。还是就是,我是直接copy过来的,如果放一起还要再整理一遍,我懒......

暂时先这样吧,估计其他3个帖子很快就回沉下去的。
3 楼 comasp 2007-12-30  
看 了 4个帖子 ,学到不少东西。
2 楼 fyting 2007-12-30  
嗯,我们在实际项目中遇到过这个问题,如果默认的timeout=30,就只创建session,不对里面写入数据,每秒几个新客户端请求,一个小时左右光session就会占用几百MB内存。使用的是tomcat5.5。
ps:lz能不能发到一个帖子里,您早上穿衣服时不喜欢鞋子袜子衣服裤子每个房间去找一样吧。
1 楼 zingers 2007-12-29  
嗯,还是很有意思的,谢谢分享经验

相关推荐

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

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

    flask-session-cookie-manager

    标题“flask-session-cookie-manager”指的是一个Python应用,它专门针对Flask框架,用于管理和操作session cookie。在Web开发中,session cookie是服务器用来跟踪用户状态的一种方式,特别是在无状态的HTTP协议上...

    tomcat-redis-session-manager-1.2-tomcat-7-java-7

    标题中的"tomcat-redis-session-manager-1.2-tomcat-7-java-7"表明这是一个针对Tomcat服务器,用于管理session的组件,版本为1.2,适配Tomcat 7和Java 7环境。这个组件的主要作用是将Tomcat的会话管理功能与Redis...

    tomcat-redis-session-manager实现session共享 配置文件

    1. **Session创建与更新**:当用户请求到达服务器时,如果创建或更新Session,Tomcat-Redis-Session-Manager会将Session对象序列化为字节数组,然后存储到Redis中,键为服务器生成的唯一Session ID。 2. **Session...

    tomcat-redis-session-manager jar包

    4. **测试验证**:部署应用后,通过创建用户会话并观察Redis中的Session数据来确认集成是否成功。 **最佳实践** 1. **安全策略**:考虑使用SSL加密Redis通信,避免Session数据在传输过程中被窃取。 2. **性能优化**...

    session-share-libs.rar

    因此,当用户登录后,服务器会为该用户创建一个唯一的Session ID,并将其存储在服务器端。每次客户端发送请求时,通过Cookie将Session ID传回服务器,服务器根据这个ID找到对应的Session数据,从而实现对用户状态的...

    tomcat-redis-session-manager源码

    首先,我们来看`Tomcat-Redis-Session-Manager`的核心功能:它将Tomcat默认的内存会话管理替换为基于Redis的分布式会话管理。这主要涉及两个关键组件:`RedisSessionManager`和`RedisSessionHandlerWrapper`。 `...

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

    当用户在网站上进行操作时,服务器会为每个用户创建一个唯一的session ID,并将其存储在客户端(通常是cookie)和服务器端(如内存或数据库)。这样,即使用户在浏览不同的页面,服务器也能识别出同一用户。 4. **...

    tomcat-redis-session-manager-master.zip

    这个项目的核心在于一个名为`TomcatRedisSessionManager`的类,它是Tomcat的`Manager`接口的实现,负责session的创建、读取、更新和销毁操作。 1. **配置集成**: 在Tomcat的`context.xml`中,我们需要添加`...

    redis-session-manager-tomcat6共享包

    3. 配置session监听器:可能需要创建一个实现了`javax.servlet.http.HttpSessionListener`接口的类,以便在session创建和销毁时进行相应操作,例如同步Redis中的session状态。 4. 重启Tomcat:完成上述配置后,重启...

    解决Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程问题

    在本文中,我们主要探讨了在使用Spring Session以及Redis作为存储方式时,由于消息监听导致创建大量线程的问题及其解决方案。我们将从Spring Session的基础知识、Redis在Spring Session中的作用、监听机制导致线程...

    memcached-session-manager

    在 memcached-session-manager 中,Kryo 可能被用作序列化策略,将 Java 对象转换为可以在网络上传输的字节流,以优化数据存储和检索的效率。 **标签解析:** 1. **memcached**:这是一个分布式内存缓存系统,用于...

    memcached-session-manager-1.8.1

    1. **Session复制**:当客户端首次访问服务器并创建session时,MSM会将session对象序列化为二进制格式,然后将其发送到配置好的Memcached服务器上。 2. **Session持久化**:每次session数据发生变化时,MSM都会自动...

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

    标题中的"tomcat7-redis-session-manager-java6-2.0.0.zip"指的是一个针对Tomcat 7的Redis Session Manager实现,版本为2.0.0,且兼容Java 6环境。这个组件的主要功能是将Tomcat服务器中的用户会话(Session)数据...

    自己实现的spring-session

    如果没有sessionId就新创建session,如果有sessionId,就去redis中查看是否有此id的记录,如果没有就新建session,如果有,还是新建session,并把redis中此session的相关数据赋值给新建的session,最后保存sessionId...

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

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

    Hibernate-nosession

    然而,在某些特定场景下,我们可能并不需要频繁地打开和关闭Session,这时“Hibernate-nosession”就显得尤为重要。本文将深入探讨Hibernate-nosession的概念、应用场景以及如何在实际代码中实现。 首先,理解什么...

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

    该软件包名为 "redis-session-manager-redis-session-manager-2.0.0.tar.gz",表明它是一个采用 tar 和 gzip 压缩格式的归档文件,通常在 Linux 或类 Unix 系统中使用。 **Redis 简介** Redis 是一个开源的、高性能...

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

    4. **实现会话处理**:根据提供的API或指南,将Session的创建、读取、更新和删除操作替换为使用Redis Session Manager的对应方法。 5. **测试**:运行应用并验证Session数据是否正确地在Redis中存储和检索。 通过...

    redis-session-manager-redis-session-manager-2.1.1.tar.gz

    当用户登录网站后,服务器会在服务器端创建一个session对象,将用户的登录信息、购物车等数据存储在其中,并通过session ID(通常是一个唯一的字符串)与客户端进行交互。客户端通常将session ID保存在cookie中,...

Global site tag (gtag.js) - Google Analytics