- 浏览: 1315664 次
- 性别:
- 来自: 成都
文章分类
- 全部博客 (471)
- 原创文章 (4)
- Database (84)
- J2SE (63)
- Web (26)
- Javascript (30)
- Lucene (11)
- os (13)
- 算法 (8)
- Webservice (1)
- Open projects (18)
- Hibernate (18)
- Spring (15)
- Css (2)
- J2ee (2)
- 综合技术 (18)
- 安全管理 (13)
- PatternsInJava (27)
- NIO (5)
- Ibatis (2)
- 书籍收藏 (1)
- quartz (7)
- 并发编程 (15)
- oracle问题 (2)
- ios (60)
- coco2d-iphone (3)
- C++ (6)
- Zookeeper (2)
- golang (4)
- animation (2)
- android (1)
最新评论
-
dandingge123:
【引用】限制UITextField输入长度的方法 -
qja:
...
对List顺序,逆序,随机排列实例代码 -
安静听歌:
现在在搞这个,,,,,哎~头都大了,,,又freemarker ...
通用大型网站页面静态化解决方案(一) -
springdata-jpa:
java quartz定时任务demo教程源代码下载,地址:h ...
Quartz 配置参考 -
马清天:
[b][/b][list][*]引用[u][/u][/list ...
通用大型网站页面静态化解决方案(一)
前阵子去面试正好被问到httpsession和cookie,今天正巧有个分享会讲到了session及负载均衡方面的东东,拿出来分享一下,以前也曾研究过负载均衡,在session共享的时候遇到了问题,这里面正好有解答,目前最好的办法是memcached。
1、Servlet Session基础
包括servlet session、http cookie原理讲解。
2、Session管理的原理
可以参考一下这篇http://blog.sina.com.cn/s/blog_4a157f470100a81z.html
有几个问题大家思考一下:
1)、怎样相对准确获取同时在线用户数,怎样实现类似于聊天室的管理员把用户踢出聊天室的功能,怎样实现类似在线聊天室的功能?
可以借鉴一下clickstream(http://www.opensymphony.com/clickstream/)的实现机制。
2)、怎样实现同一账号同一时间点只能有一个账号在线
3)、在多标签的浏览器中(例如ie8、firefox、chrome),用户开几个标签使用同一个web应用,是一个session还是多个session
4)、struts2中避免用户重复提交同一页面的机制?
5)、怎样实现类似于gmail、sina等大型网站的用户自动登录功能
6)、怎样实现类似于在线投票防止同一用户重复投票的功能。具体可以参考以前发过的《基于浏览器的客户跟踪技术概述》
还有其他类似的问题实际上也与Session有关。
3、多台服务器负载均衡情况下的Session管理
前段时间发过一篇写的《多台服务器负载均衡情况下的Session管理》文章,供参考:
在构建能够灵活地进行水平扩展、高可用性的Java Web应用程序时候,对http session的处理策略很大程度决定了应用程序的扩展性、可用性。一般而言对http session有如下的处理方案:
1、在服务器端不保存Session,完全无状态
对于不需要保持用户状态的Web应用,采用Stateless是最为恰当的,因此就不存在Session共享的问题。REST (Representational State Transfer) 算是最为典型的例子。
2、基于浏览器Cookie的Session共享
此种方案把用户相关的Session信息存储到浏览器的Cookie中,也称为客户端Session。
采用Flash Cookie、URL重写的方式传递Session信息的方案也可以归为此类。
缺点:只能够存储字符串、数值等基本类型的数据;Cookie大小存在限制;安全性;带宽及数据解压缩、网络传输性能问题。
3、基于数据库的Session共享,实现分布式应用间Session共享
此种方案把Session信息存储到数据库表,这样实现不同应用服务器间Session信息的共享。诸如Websphere Portal、Weblogic Portal都采用了类似的方案。
Tomcat Persistent Manager 的JDBC Based Store 提供了类似实现机制,表结构如下:
- create table tomcat_sessions (
- session_id varchar(100 ) not null primary key,
- valid_session char ( 1 ) not null ,
- max_inactive int not null ,
- last_access bigint not null ,
- app_name varchar(255 ),
- session_data mediumblob,
- KEY kapp_name(app_name)
- );
create table tomcat_sessions ( session_id varchar(100) not null primary key, valid_session char(1) not null, max_inactive int not null, last_access bigint not null, app_name varchar(255), session_data mediumblob, KEY kapp_name(app_name) );
优点:实现简单
缺点:由于数据库服务器相对于应用服务器更难扩展且资源更为宝贵,在高并发的Web应用中,最大的性能瓶颈通常在于数据库服务器。因此如果将 Session存储到数据库表,频繁的增加、删除、查询操作很容易造成数据库表争用及加锁,最终影响业务。
4、基于应用服务器/Servlet容器的Clustering机制
一些常用的应用服务器及Servlet容器的Clustering机制可以实现Session
Replication的功能,例如Tomcat Clustering/Session Replication、Jboss buddy
replication。
缺点:基于Clustering的Session复制性能很差,扩展性也很不行。
5、基于NFS的Session共享
通过NFS方式来实现各台服务器间的Session共享,各台服务器只需要mount共享服务器的存储Session的磁盘即可,实现较为简单。但NFS
对高并发读写的性能并不高,在硬盘I/O性能和网络带宽上存在较大瓶颈,尤其是对于Session这样的小文件的频繁读写操作。
基于磁盘阵列/SAN/NAS等共享存储的方案道理也类似。
6、基于Terracotta、Ehcache、JBossCache等Java Caching方案实现Session共享
如果系统架构是Java体系,可以考虑采用Terracotta、Ehcache、JbossCache、Oscache等Java Caching方案来实现Session 共享。
缺点:架构用于非java体系很不方便;对于是诸如静态页面之类的缓存,采用Memcached的方案比Java更为高效
7、基于Memcached/Tokyo Tyrant 等Key-Value DB的Session共享
整体说来此种方案扩展性最好,推荐使用。
原理:Tomcat 服务器提供了org.apache.catalina.session.StandardManager
和org.apache.catalina.session.PersistentManager用于Session对象的管理,可以自定义
PersistentManager的
Store 类来实现自己Memcached、Tokyo Tyrant、Redis等Key-Value DB的客户端。
以Memcached的客户端为例(摘自Use MemCacheStore in Tomcat):
- package com.yeeach; import com.danga.MemCached.MemCachedClient;
- import com.danga.MemCached.SockIOPool;
- public class MemCacheStore extends StoreBase implements Store { /**
- * The descriptive information about this implementation.
- */
- protected static String info = "MemCacheStore/1.0" ;
- /**
- * The thread safe and thread local memcacheclient instance.
- */
- private static final ThreadLocal<MemCachedClient> memclient = new ThreadLocal<MemCachedClient>();
- /**
- * The server list for memcache connections.
- */
- private List<String> servers = new ArrayList<String>();
- /**
- * all keys for current request session.
- */
- private List<String> keys = Collections.synchronizedList(newArrayList<String>());
- /**
- * Return the info for this Store.
- */
- public String getInfo() {
- return (info);
- }
- /**
- * Clear all sessions from the cache.
- */
- public void clear() throws IOException { getMemcacheClient().flushAll();
- keys.clear();
- }
- /**
- * Return local keyList size.
- */
- public int getSize() throws IOException {
- return getKeyList().size(); }
- /**
- * Return all keys
- */
- public String[] keys() throws IOException {
- return getKeyList().toArray( new String[] {}); }
- /**
- * Load the Session from the cache with given sessionId. * */
- public Session load(String sessionId) throws ClassNotFoundException,IOException {
- try {
- byte [] bytes = ( byte []) getMemcacheClient().get(sessionId);
- if (bytes == null )
- return null ;
- ObjectInputStream ois = bytesToObjectStream(bytes); StandardSession session = (StandardSession) manager.createEmptySession(); session.setManager(manager); session.readObjectData(ois);
- if (session.isValid() && !keys.contains(sessionId)) {
- keys.add(sessionId);
- }
- return session;
- } catch (Exception e) {
- return ( null );
- }
- }
- /**
- * transform a vaild Session from objectinputstream.
- * Check which classLoader is responsible for the current instance. *
- * @param bytes
- * @return ObjectInputStream with the Session object.
- * @throws IOException */
- private ObjectInputStream bytesToObjectStream( byte []bytes) throws IOException {
- ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = null ;
- Loader loader = null ;
- ClassLoader classLoader = null ;
- Container container = manager.getContainer();
- if (container != null )
- loader = container.getLoader();
- if (loader != null )
- classLoader = loader.getClassLoader();
- if (classLoader != null )
- ois = new CustomObjectInputStream(bais, classLoader); else
- ois = new ObjectInputStream(bais);
- return ois;
- }
- /**
- * remove the session with given sessionId
- */
- public void remove(String sessionId) throws IOException {
- getMemcacheClient().delete(sessionId);
- List<String> keyList = getKeyList();
- keyList.remove(sessionId);
- }
- /**
- * Store a objectstream from the session into the cache.
- */
- public void save(Session session) throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); StandardSession standard = (StandardSession) session;
- standard.writeObjectData(oos); getMemcacheClient().add(session.getId(), baos.toByteArray()); Object ob = getMemcacheClient().get(session.getId()); List<String> keyList = getKeyList(); keyList.add(session.getId());
- }
- /**
- *
- * @return
- */
- private List<String> getKeyList() {
- return keys;
- }
- /**
- * Simple instanc of the Memcache client and SockIOPool.
- * @return memchacheclient
- */
- private MemCachedClient getMemcacheClient() {
- if (memclient == null ) {
- Integer[] weights = { 1 };
- // grab an instance of our connection pool
- SockIOPool pool = SockIOPool.getInstance();
- if (!pool.isInitialized()) {
- String[] serverlist = servers.toArray(new String[] {});
- // set the servers and the weights pool.setServers(serverlist); pool.setWeights(weights);
- // set some basic pool settings
- // 5 initial, 5 min, and 250 max conns
- // and set the max idle time for a conn
- // to 6 hours pool.setInitConn(5); pool.setMinConn(5); pool.setMaxConn(250);
- pool.setMaxIdle(1000 * 60 * 60 * 6 );
- // set the sleep for the maint thread
- // it will wake up every x seconds and
- // maintain the pool size pool.setMaintSleep(30);
- // set some TCP settings
- // disable nagle
- // set the read timeout to 3 secs
- // and don't set a connect timeout pool.setNagle(false); pool.setSocketTO(3000); pool.setSocketConnectTO(0);
- // initialize the connection pool pool.initialize(); }
- // lets set some compression on for the client
- // compress anything larger than 64k memclient.get().setCompressEnable(true); memclient.get().setCompressThreshold(64 * 1024);
- }
- return memclient.get();
- }
- public List<String> getServers() {
- return servers;
- }
- public void setServers(String serverList) {
- StringTokenizer st = new StringTokenizer(serverList, ", " ); servers.clear();
- while (st.hasMoreTokens()) { servers.add(st.nextToken());
- }
- }
- }
- Tomcat 的配置文件:
- <Context path="/test" docBase= "test.war" >
- <Manager className="org.apache.catalina.session.PersistentManager" distributable= "true" >
- <Store className="com.yeeach.MemcachedStore" servers= "192.168.0.111:11211,192.168.0.112:11211" />
- </Manager>
- </Context>
package com.yeeach; import com.danga.MemCached.MemCachedClient; import com.danga.MemCached.SockIOPool; public class MemCacheStore extends StoreBase implements Store { /** * The descriptive information about this implementation. */ protected static String info = "MemCacheStore/1.0"; /** * The thread safe and thread local memcacheclient instance. */ private static final ThreadLocal<MemCachedClient> memclient = new ThreadLocal<MemCachedClient>(); /** * The server list for memcache connections. */ private List<String> servers = new ArrayList<String>(); /** * all keys for current request session. */ private List<String> keys = Collections.synchronizedList(newArrayList<String>()); /** * Return the info for this Store. */ public String getInfo() { return (info); } /** * Clear all sessions from the cache. */ public void clear() throws IOException { getMemcacheClient().flushAll(); keys.clear(); } /** * Return local keyList size. */ public int getSize() throws IOException { return getKeyList().size(); } /** * Return all keys */ public String[] keys() throws IOException { return getKeyList().toArray(new String[] {}); } /** * Load the Session from the cache with given sessionId. * */ public Session load(String sessionId) throws ClassNotFoundException,IOException { try { byte[] bytes = (byte[]) getMemcacheClient().get(sessionId); if (bytes == null) return null; ObjectInputStream ois = bytesToObjectStream(bytes); StandardSession session = (StandardSession) manager.createEmptySession(); session.setManager(manager); session.readObjectData(ois); if (session.isValid() && !keys.contains(sessionId)) { keys.add(sessionId); } return session; } catch (Exception e) { return (null); } } /** * transform a vaild Session from objectinputstream. * Check which classLoader is responsible for the current instance. * * @param bytes * @return ObjectInputStream with the Session object. * @throws IOException */ private ObjectInputStream bytesToObjectStream(byte[]bytes) throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = null; Loader loader = null; ClassLoader classLoader = null; Container container = manager.getContainer(); if (container != null) loader = container.getLoader(); if (loader != null) classLoader = loader.getClassLoader(); if (classLoader != null) ois = new CustomObjectInputStream(bais, classLoader); else ois = new ObjectInputStream(bais); return ois; } /** * remove the session with given sessionId */ public void remove(String sessionId) throws IOException { getMemcacheClient().delete(sessionId); List<String> keyList = getKeyList(); keyList.remove(sessionId); } /** * Store a objectstream from the session into the cache. */ public void save(Session session) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); StandardSession standard = (StandardSession) session; standard.writeObjectData(oos); getMemcacheClient().add(session.getId(), baos.toByteArray()); Object ob = getMemcacheClient().get(session.getId()); List<String> keyList = getKeyList(); keyList.add(session.getId()); } /** * * @return */ private List<String> getKeyList() { return keys; } /** * Simple instanc of the Memcache client and SockIOPool. * @return memchacheclient */ private MemCachedClient getMemcacheClient() { if (memclient == null) { Integer[] weights = { 1 }; // grab an instance of our connection pool SockIOPool pool = SockIOPool.getInstance(); if (!pool.isInitialized()) { String[] serverlist = servers.toArray(new String[] {}); // set the servers and the weights pool.setServers(serverlist); pool.setWeights(weights); // set some basic pool settings // 5 initial, 5 min, and 250 max conns // and set the max idle time for a conn // to 6 hours pool.setInitConn(5); pool.setMinConn(5); pool.setMaxConn(250); pool.setMaxIdle(1000 * 60 * 60 * 6); // set the sleep for the maint thread // it will wake up every x seconds and // maintain the pool size pool.setMaintSleep(30); // set some TCP settings // disable nagle // set the read timeout to 3 secs // and don't set a connect timeout pool.setNagle(false); pool.setSocketTO(3000); pool.setSocketConnectTO(0); // initialize the connection pool pool.initialize(); } // lets set some compression on for the client // compress anything larger than 64k memclient.get().setCompressEnable(true); memclient.get().setCompressThreshold(64 * 1024); } return memclient.get(); } public List<String> getServers() { return servers; } public void setServers(String serverList) { StringTokenizer st = new StringTokenizer(serverList, ", "); servers.clear(); while (st.hasMoreTokens()) { servers.add(st.nextToken()); } } } Tomcat 的配置文件: <Context path="/test" docBase="test.war"> <Manager className="org.apache.catalina.session.PersistentManager" distributable="true"> <Store className="com.yeeach.MemcachedStore" servers="192.168.0.111:11211,192.168.0.112:11211" /> </Manager> </Context>
这里只是作为测试演示了在Tomcat中集成Memcached的实现方案。并没有考虑性能、高可用、Memcached 存储Session的持久化(可以使用Memcachedb实现)、Session管理等问题。
针对Tomcat与Memcached集成有一个开源项目memcached-session-manager 功能实现相对完善,尤其是其设计思想值得借鉴。
The memcached session manager installed in a tomcat holds all
sessions locally in the own jvm, just like the StandardManager does it
as well.
Additionally, after a request was finished, the session (only if
existing) is additionally sent to a memcached node for backup.
When the next request for this session has to be served, the
session is locally available and can be used, after this second request
is finished the session is updated in the memcached node.
评论
发表评论
-
JavaScript初学者应注意的七个细节
2011-01-16 22:34 1073每种语言都有它特别的地方,对于JavaScript来说,使 ... -
META功能总结
2011-01-07 21:13 4623一、META的作用: meta标签通常用来为搜索引擎ro ... -
修改tomcat6配置,快速实现主域名、二级域名之间session共享
2010-12-02 22:04 2934项目中遇到了每个用户一个二级域名的应用,但在主域名登录后,在 ... -
实践中整理出tomcat集群和负载均衡
2010-11-25 23:33 1140(一)环境说明 (1)服务器有4台,一台安装apac ... -
Apache负载均衡+Tomcat集群
2010-10-26 21:56 1374核心提示:目标 : 使用 apache 和 tomcat ... -
Spring Ldap 域认证
2010-10-26 21:17 4437核心提示:近段时间接触了一个项目,用户认证部分是通过域认证 ... -
Spring + Tomcat 中配置连接池
2010-10-26 21:12 4812核心提示:Tomcat5 及 Tomcat6 下CP配置。 主 ... -
基于总线的消息服务(BBMS)的设计与实现
2010-10-26 21:09 2560核心提示:前言 异步事件的通知机制在比较有规模的软件设计中 ... -
JSON --- JAVA 使用方法
2010-10-25 22:51 1133JSON 即 JavaScript Object Natati ... -
大型门户网站架构分析
2010-10-24 15:48 5145千万人同时访问的网站,一般是有很多个数据库同时工作,说明白一点 ... -
fck config
2010-10-19 10:48 1499写道 * * FCKeditor - The text ... -
功能强大的fck编辑器(完整详解)
2010-10-19 10:39 3672一直都没找到完整的Fck ... -
ORACLE中的ROWID
2010-10-14 16:36 10631、rowid是一个伪列,是用来确保表中行的唯一性,它 ... -
FCKeditor在线编辑器
2010-10-14 16:20 1542FCKeditor在线编辑器 FCKeditor 这个开源 ... -
用java获取真实的ip地址
2010-10-14 16:18 2163在JSP里,获取客户端的IP地址的方法是:reques ... -
实践中整理出tomcat集群和负载均衡
2010-10-14 15:50 1119实践中整理出tomcat集群 ... -
关于MapleFetion
2010-07-28 17:40 1793http://code.google.com/p/maplef ... -
jfreechart
2010-06-28 18:13 1421http://dev.firnow.com/course/3_ ... -
Java中如何实现Comet风格的Web应用(二)
2010-03-30 17:00 2814CometProcessor 接口要求实现 event 方法 ... -
Java中如何实现Comet风格的Web应用(一)
2010-03-30 16:55 1920开始 在本文中,我将展示如何使用各种不同的 Java ...
相关推荐
NULL 博文链接:https://eggbucket.iteye.com/blog/1350360
spring4+ websocket获取httpsession
有助于学习,有助于学习JDBC技术,帮助我们在学习中理解接口和类等,以及多个接口的 作用
应用httpsession实现一个简单的验证码登录小实例,其中验证码生成工具代码可以积累使用
利用HttpSession实现Ajax请求重定向
servlet-api.jar 适用于import javax.servlet.http.HttpSession;异常 直接下载后直接导入 即可,
本篇文章主要介绍了详解SpringBoot中Session超时原理说明,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
WebSocket区分不同客户端两种方法(HttpSession和@PathParam)
ServletHttpSession DEMO
Web应用安全:HTTPSession.pptx
在WebSphereApplicationServerV7集群环境中管理HTTPsession.pdf
HTTPSession将提供一个完整的Java库来管理HTTP客户端会话。 功能(将)包括:cookie管理,HTTP身份验证,引用管理,导航历史记录,刷新语句和HTTP重定向处理。
第九章 状态管理-Cookie9.1 状态管理概述9.1.1 为什么需要状态管理9.1.2 什么是状态管理9.1.3 状态管理的两种常见模式1、写出HTTPSe
实现了HttpUrlConnetion在获取验证码后保持Session登陆的一个实例.更多好看的博客请访问我的博客:http://blog.sina.com.cn/u/2622426745
主要介绍了java使用HttpSession实现QQ的访问记录的相关资料,需要的朋友可以参考下
sevletapi.jar JavaEE开发用的jar包
详细题目描述可参照博客内文章。。。。。。。。。。。。。。。。。。。。。
anoHTTPD是个很简单的http服务器 简单到只有一个java文件 主要原理是用ServerSocket接受请求 对每一个请求的Socket创建一个线程去处理(HTTPSession) 线程内保存Socket 用Properties保存切割出来的head信息和url后...
主要介绍了JavaWeb中HttpSession中表单的重复提交,非常不错,具有参考借鉴价值,需要的朋友可以参考下