tomcat+memcached+shiro+spring实现session共享
背景
普通的项目部署,如果使用一台tomcat,那么就不存在什么session共享的问题了,如果后台部署了多个tomcat,那么多个tomcat之间需要考虑这个问题,session共享。默认tomcat的session信息是存储在本机的,所以多个tomcat,就造成了session有可能不一致的情况。当我们一台服务器宕掉的时候,他所存储的session信息也会丢失,这时我们需要一个缓存,来把多个tomcat的session信息统一管理,这样当一台服务挂了,用户可以无缝连接到另一个服务器上,不用再重新登陆。
方法
这里引入了一个概念,叫做session的粘性架构:
1.黏性Session
黏性Session: 是对于用户和应用服务器之间、应用服务器和缓存的集中管理或备份服务器之间的关系。如上图的第一种架构中就属于粘性Session,客户端和应用服务器有一定的关系。这种关系的Session就属于粘性Session。
2.非黏性Session
非黏性Session:像上图的第二种架构客户端和应用服务器没有任何Session的相关的联系,客户端有请求,应用服务器就去Session池中查询,有就进行响应,没有就创建、添加到Session池中,然后进行响应。
简单来讲就是:
黏性Session:当用户发出第一个请求后,负载均衡器动态的把该用户分配到某个节点,并记录该节点的路由,以后该用户的所有请求都绑定到这个路由,用户只会与该server发生交互,这种策略被称为粘性session(sticky session)。反之则是非黏性Session。
配置
环境:
Windows下 tomcat8 2台 memcached1台 Nginx1台
jar包:
加载memcached-session-manager-tc8-2.1.1.jar注意 你是内个版本的tomcat就下载什么版本我这用的是8,所以用tc8.
jar包下载地址
https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration
关于memcached-session-manager的介绍,具体参见官网:http://code.google.com/p/memcached-session-manager/,也可以参考:http://gong1208.iteye.com/blog/1596120
基于memcached和tomcat的配置:
1.粘性session:
修改tom1和tom2的context.xml,在Context标签中添加如下代码
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.0.167:11211,n2:192.168.0.167:11212"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
2…非粘性session:
修改tom1和tom2的context.xml,在Context标签中添加如下代码
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.0.167:11211,n2:192.168.0.167:11212"
sticky="false"
sessionBackupAsync="false"
lockingMode="uriPattern:/path1|/path2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
session共享的配置:
需要在tomcat的server.xml文件下:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="node1">
node1是第几个tomcat就写node几。
解除这个标签的注释:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="10"/>
还需要在你的web项目的web.xml中添加注解 就在下边加就可以。
测试
在/tomcat/webapps下添加index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ClusterApp Test</title>
</head>
<body>
访问的Nginx IP:<%=request.getServerName()%>
<BR>
Tomcat SessionPort:<%=request.getServerPort()%>
<%
out.println("Tomcat Server Info=" + request.getLocalAddr() + " : " + request.getLocalPort() + "<br>");
out.println("当前 Session ID=" + session.getId() + "<br>");
%>
<%
String dataName = request.getParameter("dataName");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.println("<b>Session列表</b><br>");
System.out.println("Session列表");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String) e.nextElement();
String value = session.getAttribute(name).toString();
out.println(name + " = " + value + "<br>");
System.out.println(name + " = " + value);
}
%>
<form action="sessiontest.html" method="POST">
名称:<input type=text size=20 name="dataName"> <br/>
值:<input type=text size=20 name="dataValue"> <br/>
<input type=submit text="提交">
</form>
</body>
遇到的坑:
memcache和tomcat必须是一对一才有效果,两个tomcat对用一个memcached不行怎么试都不行。