`
wbj0110
  • 浏览: 1603119 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

高扩展Web应用HTTP 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) 
          ); 

        优点:实现简单 

        缺点:由于数据库服务器相对于应用服务器更难扩展且资源更为宝贵,在高并发的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): 

Java代码   收藏代码
  1. package com.yeeach;  
  2. import com.danga.MemCached.MemCachedClient;   
  3. import com.danga.MemCached.SockIOPool;  
  4.   
  5. public class MemCacheStore extends StoreBase implements Store {  
  6.   
  7.     /** 
  8.      * The descriptive information about this implementation. 
  9.      */  
  10.     protected static String info = "MemCacheStore/1.0";  
  11.   
  12.     /** 
  13.      * The thread safe and thread local memcacheclient instance. 
  14.      */  
  15.     private static final ThreadLocal<MemCachedClient> memclient = new ThreadLocal<MemCachedClient>();  
  16.   
  17.     /** 
  18.      * The server list for memcache connections. 
  19.      */  
  20.     private List<String> servers = new ArrayList<String>();  
  21.   
  22.     /** 
  23.      * all keys for current request session. 
  24.      */  
  25.     private List<String> keys = Collections  
  26.             .synchronizedList(new ArrayList<String>());  
  27.   
  28.     /** 
  29.      * Return the info for this Store. 
  30.      */  
  31.     public String getInfo() {  
  32.         return (info);  
  33.     }  
  34.   
  35.     /** 
  36.      * Clear all sessions from the cache. 
  37.      */  
  38.     public void clear() throws IOException {  
  39.         getMemcacheClient().flushAll();  
  40.         keys.clear();  
  41.     }  
  42.   
  43.     /** 
  44.      * Return local keyList size. 
  45.      */  
  46.     public int getSize() throws IOException {  
  47.         return getKeyList().size();  
  48.     }  
  49.   
  50.     /** 
  51.      * Return all keys 
  52.      */  
  53.     public String[] keys() throws IOException {  
  54.         return getKeyList().toArray(new String[] {});  
  55.     }  
  56.   
  57.     /** 
  58.      * Load the Session from the cache with given sessionId. 
  59.      * 
  60.      */  
  61.     public Session load(String sessionId) throws ClassNotFoundException,  
  62.             IOException {  
  63.   
  64.         try {  
  65.   
  66.             byte[] bytes = (byte[]) getMemcacheClient().get(sessionId);  
  67.             if (bytes == null)  
  68.                 return null;  
  69.             ObjectInputStream ois = bytesToObjectStream(bytes);  
  70.   
  71.             StandardSession session = (StandardSession) manager  
  72.                     .createEmptySession();  
  73.             session.setManager(manager);  
  74.             session.readObjectData(ois);  
  75.             if (session.isValid() && !keys.contains(sessionId)) {  
  76.                 keys.add(sessionId);  
  77.             }  
  78.             return session;  
  79.   
  80.         } catch (Exception e) {  
  81.             return (null);  
  82.         }  
  83.     }  
  84.   
  85.     /** 
  86.      * transform a vaild Session from objectinputstream. 
  87.      * Check which classLoader is responsible for the current instance. 
  88.      * 
  89.      * @param bytes 
  90.      * @return ObjectInputStream with the Session object. 
  91.      * @throws IOException 
  92.      */  
  93.     private ObjectInputStream bytesToObjectStream(byte[] bytes)  
  94.             throws IOException {  
  95.         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);  
  96.         ObjectInputStream ois = null;  
  97.         Loader loader = null;  
  98.         ClassLoader classLoader = null;  
  99.         Container container = manager.getContainer();  
  100.         if (container != null)  
  101.             loader = container.getLoader();  
  102.         if (loader != null)  
  103.             classLoader = loader.getClassLoader();  
  104.         if (classLoader != null)  
  105.             ois = new CustomObjectInputStream(bais, classLoader);  
  106.         else  
  107.             ois = new ObjectInputStream(bais);  
  108.         return ois;  
  109.     }  
  110.   
  111.     /** 
  112.      * remove the session with given sessionId 
  113.      */  
  114.     public void remove(String sessionId) throws IOException {  
  115.         getMemcacheClient().delete(sessionId);  
  116.         List<String> keyList = getKeyList();  
  117.         keyList.remove(sessionId);  
  118.     }  
  119.   
  120.     /** 
  121.      * Store a objectstream from the session into the cache. 
  122.      */  
  123.     public void save(Session session) throws IOException {  
  124.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  125.         ObjectOutputStream oos = new ObjectOutputStream(baos);  
  126.         StandardSession standard = (StandardSession) session;  
  127.         standard.writeObjectData(oos);  
  128.         getMemcacheClient().add(session.getId(), baos.toByteArray());  
  129.         Object ob = getMemcacheClient().get(session.getId());  
  130.         List<String> keyList = getKeyList();  
  131.         keyList.add(session.getId());  
  132.     }  
  133.   
  134.     /** 
  135.      * 
  136.      * @return 
  137.      */  
  138.     private List<String> getKeyList() {  
  139.         return keys;  
  140.     }  
  141.   
  142.     /** 
  143.      * Simple instanc of the Memcache client and SockIOPool. 
  144.      * @return memchacheclient 
  145.      */  
  146.     private MemCachedClient getMemcacheClient() {  
  147.         if (memclient == null) {  
  148.   
  149.             Integer[] weights = { 1 };  
  150.             // grab an instance of our connection pool  
  151.             SockIOPool pool = SockIOPool.getInstance();  
  152.             if (!pool.isInitialized()) {  
  153.                 String[] serverlist = servers.toArray(new String[] {});  
  154.                 // set the servers and the weights  
  155.                 pool.setServers(serverlist);  
  156.                 pool.setWeights(weights);  
  157.   
  158.                 // set some basic pool settings  
  159.                 // 5 initial, 5 min, and 250 max conns  
  160.                 // and set the max idle time for a conn  
  161.                 // to 6 hours  
  162.                 pool.setInitConn(5);  
  163.                 pool.setMinConn(5);  
  164.                 pool.setMaxConn(250);  
  165.                 pool.setMaxIdle(1000 * 60 * 60 * 6);  
  166.   
  167.                 // set the sleep for the maint thread  
  168.                 // it will wake up every x seconds and  
  169.                 // maintain the pool size  
  170.                 pool.setMaintSleep(30);  
  171.   
  172.                 // set some TCP settings  
  173.                 // disable nagle  
  174.                 // set the read timeout to 3 secs  
  175.                 // and don't set a connect timeout  
  176.                 pool.setNagle(false);  
  177.                 pool.setSocketTO(3000);  
  178.                 pool.setSocketConnectTO(0);  
  179.   
  180.                 // initialize the connection pool  
  181.                 pool.initialize();  
  182.             }  
  183.   
  184.             // lets set some compression on for the client  
  185.             // compress anything larger than 64k  
  186.   
  187.             memclient.get().setCompressEnable(true);  
  188.             memclient.get().setCompressThreshold(64 * 1024);  
  189.         }  
  190.         return memclient.get();  
  191.     }  
  192.   
  193.     public List<String> getServers() {  
  194.         return servers;  
  195.     }  
  196.   
  197.     public void setServers(String serverList) {  
  198.         StringTokenizer st = new StringTokenizer(serverList, ", ");  
  199.         servers.clear();  
  200.         while (st.hasMoreTokens()) {  
  201.             servers.add(st.nextToken());  
  202.         }  
  203.     }  
  204.   
  205. }  


Tomcat 的配置文件: 

Xml代码   收藏代码
  1. <Context path="/test" docBase="test.war">  
  2.     <Manager className="org.apache.catalina.session.PersistentManager"  
  3.         distributable="true">  
  4.         <Store className="com.yeeach.MemcachedStore"  
  5.             servers="192.168.0.111:11211,192.168.0.112:11211" />  
  6.     </Manager>  
  7. </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. 



    对于采用Tokyo Tyrant、Redis等当下流行的Key-Value DB实现机制类似。

 

 

大家可以加我个人微信号:scccdgf

 

 

或者关注soledede的微信公众号:soledede
  
分享到:
评论

相关推荐

    springboot +shiro+redis实现session共享(方案二)1

    本文档旨在介绍如何使用 Spring Boot、Shiro 和 Redis 实现分布式 session 共享,以解决 Web 应用程序的登录 session 统一问题。 2. 相关依赖 在实现 session 共享之前,需要在项目中引入相关依赖项,包括: * ...

    session共享方案(tomcat8+redis共享session)

    这种Session共享方案的优势在于,Redis作为一个中心化的Session存储,减少了服务器之间的通信开销,提高了系统的可扩展性。同时,由于Redis支持多线程访问,因此在高并发场景下能保证较高的性能。 需要注意的是,...

    web项目集群时共享session方案实践

    `WEB-INF`和`META-INF`目录通常包含Web应用的配置文件和类路径信息,它们可能涉及到Session共享的相关配置。 总的来说,Web项目集群时共享Session是一项重要的任务,它关系到用户体验和系统的可扩展性。理解并掌握...

    tomcat集群session共享解决方案

    本篇文章将深入探讨Tomcat集群中session共享的解决方案,以及相关的应用知识。 1. **Session复制**:这是最基础的session共享方法。通过配置Tomcat的`cluster`模块,可以设置session复制策略。每当一个session在...

    tomcat8集群实现session共享,内含session共享包

    在这个场景中,我们关注的是如何在Tomcat集群环境中实现Session共享,以便提高应用程序的可扩展性和可用性。标题和描述提到的“session共享包”是解决这一问题的关键。 **什么是Session?** 在Web应用中,Session是...

    PHP实现多服务器session共享之memcache共享.rar

    掌握这些知识对于构建高可用、可扩展的Web应用至关重要。通过实践和学习提供的文档,如"PHP实现多服务器session共享之memcache共享.doc",开发者可以深入理解并掌握这一技术,提升网站的用户体验和整体性能。

    asp.net不同应用程序Session共享

    总结来说,实现ASP.NET不同应用程序间的Session共享需要对Session的工作机制有深入理解,并可能涉及修改`web.config`配置、创建自定义Session提供者或者调整IIS设置。在实施过程中,务必考虑性能、安全性和可扩展性...

    SSM项目集成shiro搭建session共享

    总之,这个项目通过合理的技术选型和集成,实现了基于SSM的Web应用的安全控制和session共享,提高了系统的可扩展性和用户体验。在实际开发中,还需要考虑性能优化、异常处理、安全性等问题,以保证系统的稳定和健壮...

    ssm+redis 实现session共享

    通过这样的集成,我们可以构建出一个可扩展、高可用的分布式Web应用,有效解决了Session共享问题。同时,结合Nginx的负载均衡能力,能够进一步提高系统的稳定性和处理能力。对于大型Web应用来说,这是一种常见的解决...

    session共享项目测试

    此外,还可以考虑使用其他的Session共享方案,如基于Token的认证机制(JWT,JSON Web Tokens)或Cookie-based方案,但这需要根据具体业务需求和技术栈进行选择。 总之,"session共享项目测试"是一个旨在解决分布式...

    C#不同域名之间的Session共享

    本篇文章将深入探讨C#中如何实现不同域名之间的Session共享,以及这一功能的重要性和应用场景。 Session共享的主要目的是在多个网站或应用之间保持用户的登录状态和其他个性化信息,提高用户体验。默认情况下,ASP...

    session共享插件

    【session共享插件】是一种用于Java应用程序的解决方案,旨在实现跨服务器的会话状态共享。在Web应用中,session是服务器用来存储用户特定信息的一种机制,例如登录状态、购物车内容等。当应用部署在多台服务器上时...

    Spring Session + redis实现session共享

    在现代Web应用开发中,session共享是一个至...通过将session数据存储在Redis中,我们可以轻松地扩展Web应用的服务器集群,同时保持用户状态的一致性。了解并熟练掌握这种技术对于构建高可用、可伸缩的Web服务至关重要。

    springboot + redis实现session共享

    在现代Web应用开发中,session共享是一个至关重要的问题...总之,Spring Boot与Redis结合实现的session共享方案,不仅解决了分布式环境下的状态管理问题,还提升了系统的性能和可扩展性,是现代Web应用的一种理想选择。

    nginx+tomcat+redis完成session共享

    在IT行业中,构建高可用和高性能的Web应用架构是...通过这种方式实现session共享,不仅可以提高应用的可扩展性,还能减少因服务器故障导致的用户体验中断。记住,实际部署时还需要考虑安全性、性能优化和其他运维因素。

    Tomcat实现session共享demo

    本示例将深入探讨如何使用Tomcat8与Redis相结合来实现session共享,这是一个高效且广泛应用的解决方案。 首先,我们需要理解什么是Session。在Web应用中,Session是用来跟踪用户状态的一种机制。当用户登录后,...

    tomcat集群session共享

    然而,当涉及到用户状态管理时,如通过HTTP协议的session进行用户登录状态跟踪,集群中的session共享就成为一个关键问题。 session共享的主要目的是确保用户在集群中的任意一台服务器上操作都能被其他服务器识别,...

    redissession共享代码

    总的来说,Redis Session共享是提高Web应用可扩展性和可用性的一种有效方法。通过对"redissession共享代码"的深入研究和实践,开发者可以掌握这一技术,并将其应用到实际项目中,提升用户体验和系统稳定性。

    tomcat7集群实现session共享

    当我们谈论“Tomcat7集群实现session共享”时,我们关注的是如何在多个Tomcat实例之间有效地同步用户会话信息,以便在集群环境中提供高可用性和负载均衡。 首先,理解session共享的重要性。在Web应用中,session是...

    spring session实现session共享

    Spring Session 是一个开源项目,由 Pivotal Software 开发,旨在提供一种在分布式环境中实现Session共享的解决方案。在传统的Web应用中,Session信息通常存储在单个服务器的内存中,当应用部署在集群或者分布式环境...

Global site tag (gtag.js) - Google Analytics