采用Memcached实现分布式Session
欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。
欢迎跳转到本文的原文链接:https://honeypps.com/backend/distributed-session-with-memcached/
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/InstantiatorStrategyat 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.InstantiatorStrategyat 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服务器中。
欢迎跳转到本文的原文链接:https://honeypps.com/backend/distributed-session-with-memcached/
参考资料:
- LVS+Keepalived实现负载均衡和双机热备
- MSM–Memcached_Session_Manager介绍及使用
- memcached-session-manager配置
- 《大型分布式网站架构设计与实践》陈康贤著
欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。
采用Memcached实现分布式Session相关推荐
- 分布式Session共享(二):tomcat+memcached实现session共享 - 萝卜兔子 - 博客园
分布式Session共享(二):tomcat+memcached实现session共享 - 萝卜兔子 - 博客园 http://www.cnblogs.com/notDog/p/5341219.htm ...
- 基于ZooKeeper的分布式Session实现
基于ZooKeeper的分布式Session实现 [转 http://blog.csdn.net/jacktan/article/details/6112806] 认识ZooKeeper ZooKee ...
- Java Web学习总结(20)——基于ZooKeeper的分布式session实现
1. 认识ZooKeeper ZooKeeper-- "动物园管理员".动物园里当然有好多的动物,游客可以根据动物园提供的向导图到不同的场馆观赏各种类型的动物,而不是像走在原始 ...
- 分布式Session的几种实现方式
一.分布式Session的几种实现方式 1.基于数据库的Session共享 2.基于NFS共享文件系统 3.基于memcached 的session,如何保证 memcached 本身的高可用性? 4 ...
- ASP.NET性能优化之分布式Session
如果我们正在使用Session,那么构建高性能可扩展的ASP.NET网站,就必须解决分布式Session的架构,因为单服务器的SESSION处理能力会很快出现性能瓶颈,这类问题也被称之为Session ...
- 分布式锁和分布式事务和分布式Session
分布式锁和分布式事务 分布式锁 基于MySQL数据库 这种方式一般采用数据库乐观锁,不推荐使用 基于redis 加锁:setnx命令,key是锁的唯一标志,可以为想要加锁的资源设置对应的key,val ...
- sae session php,SAE 分布式session丢失的问题
分布式Session SAE Java 平台中的应用部署在分布式环境中,因此SAE为每个应用提供了分布式Session功能,以保证Session能多节点共享.Session信息使用分布式的Memcac ...
- 170222、使用Spring Session和Redis解决分布式Session跨域共享问题
使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...
- Spring Boot(十一)Redis集成从Docker安装到分布式Session共享
2019独角兽企业重金招聘Python工程师标准>>> 一.简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并 ...
最新文章
- Netkiller Architect 手札之前言
- php 数组重新打乱_PHP 将数组打乱 shuffle函数的用法及简单实例
- python 用if判断一个数是不是整数_五天学会Python基础02(下)
- silverlight 学习笔记 (五): MVVM Light Toolkits 之 RealCommand
- 解决 fprintd-0.1-19.git04fd09cfa.el6 crash问题
- mile for gallon 汽车省油
- 开源虎墩同名电影《小虎墩大英雄》定档大年初一
- 07.30《jQuery》——1.1DOM对和jQuery对象的转化
- java yaml dump方法_yamlyaml.load与yaml.dump方法
- Android ScrollView内部组件设置android:layout_height=fill_parent无效的解决办法
- 韩顺平php视频笔记69 静态变量与静态方法
- Python自动控制鼠标中键滚动并截屏保存图像
- 有线网络高可用项目实施方案(更新中)
- 怎样让开源项目看起来“高大上”
- Wake On Lan(WOL)失败的原因
- js动态添加元素时绑定onclick函数
- python问题 Traceback (most recent call last)
- SEO技巧:快速学会SEO技术的方法
- 我经历的日本东京交通
- 哈佛职场情商课读书笔记
热门文章
- Java8函数式编程(1)--Principle
- python一共有多少个内置函数_Python 35个内置函数,你都ok吗?
- 财政指标是什么意思_in the black是“在黑暗中”吗?那in the dark是什么意思?
- 201112阶段二qt图形视图框架
- µVISION: Error: Encountered an improper argument
- 一种非常实用的系统掉电检测和保护电路---摘自:周立功单片机
- git使用的一些常用命令
- 浅析Windows7的睡眠、休眠、混合睡眠、离开模式
- MySQL Workbench的使用教程 (初级入门版)
- RTEMS 的 AT91SAM9260 移植(8): 编译