采用Memcached实现分布式Session

 memcached-session-manager是一个开源的高可用的Tomcat session共享解决方案,它支持Sticky模式和Non-Sticky模式。Sticky模式表示每次请求都会被映射到同一台后端Web服务器,知道该Web服务器宕机,这样session可先存放在服务器本地,等到请求处理完成再同步到后端memcached服务器;而当Web服务器宕机时,请求被映射到其他Web服务器,这时候,其他Web服务器可以从后端memcache中恢复session。对于Non-Sticky模式来说,请求每次映射的后端Web服务器是不确定的,当请求到来时,从memcached中加载session;当请求处理完成时,将session再协会到memcached。

 以Non-Sticky模式为例,首先需要安装memcached的服务器,这个在上一篇中已经讲述过了。然后在Tomcat的$CATALINA_HOME/conf/context.xml文件配置SessionManager,具体配置如下:

    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
      memcachedNodes="n1:10.10.195.112:11211"
      sticky="false"
      sessionBackupAsync="false"
      sessionBackupTimeout="1000"
      lockingMode="auto"
      requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
      transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />  

 其中,memcachedNodes指定了memcached的节点;sticky表示是否采用sticky模式;sessionBackuoAsync表示是否采用异步方式备份session;lockingMode表示session的锁定模式;auto表示对于只读请求,session将不会被锁定,如果包含写入请求,则session会被锁定;requestUriIgnorePattern表示忽略的url; transcoderFactoryClass用来指定序列化的方式,这里采用的是Kryo序列化,也是memcached-session-manager比较推荐的一种序列化方式。也可以采用其他序列化方式,譬如:javolution-serializer, xstream-serializer, flexjson-serializer。

 memcached-session-manager依赖于memcached-session-manager-{version}.jar,如果使用的是tomcat6,则还需要下载memcached-session-manager-tc6-{version}.jar,如果是tomcat7则采用memcached-session-manager-tc7-{version}.jar的包(博主采用的是tomcat7+jdk7)。还需要spymemcached-2.7.3.jar,在启动tomcat之前需要将这些jar包放到tomcat的lib目录下。如果采用Kryo方式序列化,还需要加入其他一些包,所有包如下:

注意这些包的版本,搞错一下就不能实现其功能。这里博主已经整理好了,可以在这里下载。


常见错误

1 启动tomcat出现错误案例1

严重: Error manager.start()
org.apache.catalina.LifecycleException: Failed to start component [de.javakaffee.web.msm.MemcachedBackupSessionManager[/Architecture]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5501)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:672)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1859)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NoClassDefFoundError: org/objenesis/strategy/InstantiatorStrategy
    at de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory.getTranscoder(KryoTranscoderFactory.java:64)
    at de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory.createTranscoder(KryoTranscoderFactory.java:47)
    at de.javakaffee.web.msm.MemcachedSessionService.createTranscoderService(MemcachedSessionService.java:493)
    at de.javakaffee.web.msm.MemcachedSessionService.startInternal(MemcachedSessionService.java:448)
    at de.javakaffee.web.msm.MemcachedBackupSessionManager.startInternal(MemcachedBackupSessionManager.java:535)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 12 more
Caused by: java.lang.ClassNotFoundException: org.objenesis.strategy.InstantiatorStrategy
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 18 more

这个是包版本问题,memcached-session-manager以及msm-kryo-serializer版本不对。

2 启动tomcat出现错误案例2

严重: Error manager.start()
org.apache.catalina.LifecycleException: Failed to start component [de.javakaffee.web.msm.MemcachedBackupSessionManager[]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5501)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1245)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1895)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NoSuchMethodError: de.javakaffee.web.msm.MemcachedSessionService$SessionManager.getContainerClassLoader()Ljava/lang/ClassLoader;
    at de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory.createTranscoder(KryoTranscoderFactory.java:47)
    at de.javakaffee.web.msm.MemcachedSessionService.createTranscoderService(MemcachedSessionService.java:449)
    at de.javakaffee.web.msm.MemcachedSessionService.startInternal(MemcachedSessionService.java:425)
    at de.javakaffee.web.msm.MemcachedBackupSessionManager.startInternal(MemcachedBackupSessionManager.java:509)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 12 more

这个也是包版本问题,msm-kryo-serializer版本不对

3 在context.xml中配置failoverNodes节点,如下

    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
      memcachedNodes="n1:10.10.195.112:11211"
      sticky="false"
      failoverNodes="n1"
      sessionBackupAsync="false"
      lockingMode="auto"
      requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
      transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    /> 

启动tomcat报错:

严重: Error manager.start()
org.apache.catalina.LifecycleException: Failed to start component [de.javakaffee.web.msm.MemcachedBackupSessionManager[/Architecture]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5501)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:672)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1859)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: For a single memcached node there should/must no failoverNodes be specified.
    at de.javakaffee.web.msm.MemcachedNodesManager.createFor(MemcachedNodesManager.java:224)
    at de.javakaffee.web.msm.MemcachedSessionService.createMemcachedNodesManager(MemcachedSessionService.java:445)
    at de.javakaffee.web.msm.MemcachedSessionService.startInternal(MemcachedSessionService.java:410)
    at de.javakaffee.web.msm.MemcachedBackupSessionManager.startInternal(MemcachedBackupSessionManager.java:509)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 12 more

可以看到报错中“Caused by: java.lang.IllegalArgumentException: For a single memcached node there should/must no failoverNodes be specified.”这句,需要把failoverNodes去掉。


应用举例

 这里博主采用keepalived+lvs进行负载均衡搭建。详细可以参考LVS+Keepalived实现负载均衡和双机热备,不了解也没关系,这个不是本篇的重点。

主机ip:10.10.195.107
备机ip:10.10.195.187
虚拟ip:10.10.195.188

 (配的是双机热备+负载均衡,主备机会虚拟出一个访问的ip,当主机宕机时,会自动切换到备机,对于用户而言完全透明。了解即可)

 在主备机web路径的根目录下放入test.jsp,代码如下(备机的就把 10.10.195.107换成10.10.195.187):

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%@ page session="true" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Memcached-session-manager</title>
</head>
<body >
    10.10.195.107
    <%
        out.print("<br> SESSION-ID:"+session.getId()+"<br>");
    %>
</body>
</html>

通过浏览器访问:http://10.10.195.188:8080/test.jsp
可以看到页面显示:

10.10.195.107
SESSION-ID:6F9B1255A1C9E3F7D5FC144DD81217CD-n1

在主机中输入: sudo service keepalived stop之后(切换到备机),页面显示:

10.10.195.187
SESSION-ID:6F9B1255A1C9E3F7D5FC144DD81217CD-n1

可以看到访问的页面变了,但是session并没有改变,因为它存在memcached服务器中。



参考资料:
1. LVS+Keepalived实现负载均衡和双机热备
2. MSM–Memcached_Session_Manager介绍及使用
3. memcached-session-manager配置
4. 《大型分布式网站架构设计与实践》陈康贤著

时间: 2024-11-20 05:43:48

采用Memcached实现分布式Session的相关文章

ASP.NET通过分布式Session提升性能_实用技巧

如果我们正在使用Session,那么构建高性能可扩展的ASP.NET网站,就必须解决分布式Session的架构,因为单服务器的 SESSION处理能力会很快出现性能瓶颈,这类问题也被称之为Session同步.微软有自己的分布式Session的解决方案,那就是 SessionStateServer,我们可以参考: ASP.NET Session State Partitioning  http://blog.maartenballiauw.be/post/2008/01/23/ASPNET-Ses

memcached的分布式

今天写点周末在火车上看的memcached的东西: 一:memcached的分布式          虽然memcached被称为"分布式"缓存服务器,但是服务器端并没有"分布式"的功能.而是通过客户端来实现的.          Memcached分布式原理:                                假设有5台memcached服务器:node1,node2- node5.现在要保存键为key1,key2-key10的数据.首先往memcac

如何基于MongoDB打造.Net的分布式Session子系统

Taobao有她自己的分布式session框架,.net阵营也不能落后了,在下做了个 基于MongoDB的支持最多26台MongoDB的分布式Session框架. 先看看配置文件: <?xml version="1.0" encoding="utf-8" ?> <MongoDBSession> <DbName>SessionDB</DbName> <IdentityMap Identity="A&quo

采用atomikos做分布式单向多对一关联报错

问题描述 采用atomikos做分布式在A库的实体类pojo1与B库的实体类pojo2单向多对一关联Causedby:org.hibernate.AnnotationException:@OneToOneor@ManyToOneoncom.Pojo.pojo2referencesanunknownentity:com.Pojo2 解决方案

python操作memcached以及分布式的例子

memcached 是以 LiveJournal 旗下 Danga Interactive 公司的 Brad Fitzpatric 为首开发的一款软件.现在已成为 mixi.Facebook.LiveJournal 等众多服务中提高 Web 应用扩展性的重要因素. 许多 Web 应用都将数据保存到 RDBMS 中,应用服务器从中读取数据并在浏览器中显示.但随着数据量的增大.访问的集中,就会出现 RDBMS 的负担加重.数据库响应恶化.网站显示延迟等重大影响.这时就该 memcached 大显身手

Redis学习笔记~StackExchange.Redis实现分布式Session

对于多WEB的环境现在已经是必须的了,很难想像一台WEB服务器面对百万并发的响应,所以,我们需要多台WEB服务器集群合作,来缓解这种高并发,高吞吐的场景,而对于多WEB的场景又会有个问题出现,即session存储的问题,如一个用户登陆后,把一个状态信息存储到当前WEB服务器的session里,而你请求其它页面时,很可能就被路由到另一台服务器了,这时,session也就丢了,而对于这种情况,有人把redis这个存储中间件想了起来,对它进行了封装,就有了今天基于redis的session共享机制.

构架高性能WEB网站的知识点

前言: 对于构架高性能的web网站大家都很感兴趣,本文从几点粗谈高性能web网站需要考虑的问题. HTML静态化 什么是html静态化? 说得简单点,就是把所有不是.htm或者.html的页面改为.htm或者.html 1.纯静态页面 当用户访问是,不需要经过服务器解析,直接就可以传送到客户端,此类型的页面,由于不需要解析就能直接访问,一般情况下,比动态页面的执行速度快. 2.静态化 页面静态化就是用动静结合的方式将动态网站生成静态网站来保存.这是实实在在的html文件,也就是静态页面. 3.

由&amp;quot;缓存&amp;quot;到&amp;quot;Memcached分布式缓存&amp;quot;

[学习背景] 在ITOO4.0的时候,自己听了师哥师姐的技术分享,从那开始,Memcached 就留在脑海中了.现在,我们开始了ITOO4.1,在师父的指导下,开始缓存的学习.自然地,我第一时刻想到的便是Memcached. [学习阶梯] 在正是进入Memcached之前,自己先了解了些关于"缓存"的知识. 一.什么是缓存 用来暂时存储数据,避免频繁连接数据库或磁盘文件.一般来说,缓存比数据库或磁盘容量更小,但存取速度快. 二.缓存的作用 存储频繁访问的数据:临时存储耗时的计算结果:内

如何将PHP session信息缓存到memcached里面

一.场景介绍 &http://www.aliyun.com/zixun/aggregation/37954.html">nbsp; 用户在利用PHP搭建网站时,会把一些信息存放在$_SESSION全局变量里,可以很方便的存取.在PHP的ini配置文件 里面提供了[Session]相关配置,可以支持将信息存到文件或memcached服务器里面.由配置项session.save_handler = memcached决定.大多数场景,该session数据并不需要持久化,且为了提升网站性