文档章节

分布式系统中统一会话(tomcat session共享)的实现

weiliu007
 weiliu007
发布于 2017/04/04 10:19
字数 1362
阅读 51
收藏 0
点赞 0
评论 0

 

在分布式系统中,我们想要实现统一会话有以下5种常用的实现方式:

一:tomcat本身集群(不推荐,性能比较差)

二:msm(谷歌出品)

MSM( memcached-session-manager  )是什么


MSM是一个高可用的Tomcat集群中Session共享解决方案。 
MSM特性

支持黏性、非黏性Session 可处理Tomcat故障转移 可处理Memcached故障转移 插件式session序列化 允许异步保存session

黏性、非黏性Session的方案

最大的区别在于: 
     1:黏性Session的方案,适合于前端的负载均衡器能保证,每个用户的请求都路由到同一个Tomcat上这种场景 
      2:黏性Session的方案,会把Memcached中的数据同步存放到本地的Http Session区。

SESSIONID的格式

由于MSM知道Memcached节点列表,因此SESSIONID中会带着这些节点,比如: 09D01FE736F0C682A2AA71D464EC5ED9-n1


MSM安装配置

1:环境是Tomcat8,需要的jar包参见下面
2:把这些jar包添加到Tomcat8/lib,或者是应用自身的lib里面
3:修改context.xml或server.xml文件中的<Context>节点,示例如下:

(1)使用non-sticky  session,memcached缓存
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:localhost:11211,n2:192.168.1.106:2222"
sticky="false"
sessionBackupAsync="false"
lockingMode="auto" requestUriIgnorePattern=“.*\.(ico|png|gif|jpg|css|js)$”
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFac tory" />
(2)使用sticky session,memcached缓存
 a:添加jvmroute参数,每个Tomcat配置的这个值要不一样,如下:
    <Engine name="Catalina"defaultHost="localhost“ jvmRoute="tomcat1">
 b:把上面配置中的sticky设置为true
 c:不用配置lockingMode,这个是只有非黏性session才使用,默认值为none none: 从不对session进行锁定
   all:  session将一直被锁定,直到请求结束
   auto: 对于只读请求,session将不会被锁定,如果是非只读请求,则会被锁定 uriPattern:<regexp>:
   通过正则表达式的方式来对请求uri以及查询字符串进行匹配,只有匹配上的才会被锁定。 
 d:添加failoverNodes配置,用来指定备用的memcached节点

4:配置后启动Tomcat,如果没有报错就表示配置好了
5:可以自定义序列化的方案,除了默认的Java序列化外,常见的还有:kryo、 javolution、xstream、flexjson等,可以下载相应的jar,并修改 transcoderFactoryClass。
建议使用maven来管理并下载需要的jar





查看Memcached的数据 

1:连接到Memcached服务器:telnet 192.168.1.106 2222
2:查看多有的Item:stats items
3:输出Item:stats  cachedump itms后面的数据    0 ,0表示显示全部数据
4:输出具体的数据:get  key ,key就是上面item后面的数据

参考链接:http://blog.csdn.net/a__java___a/article/details/8738932

三:redisclusterSessionManager

首先下载解压

https://github.com/ran-jit/TomcatClusterRedisSessionManager/releases/download/1.1.1/TomcatRedisSessionManager-1.1.1.zip
第一步:上面解压里面的jar包拷贝到tomcat目录里面lib下面
第二步:把RedisDataCache.properties拷贝到 tomcat/conf/下面
第三步:在tomcat/conf目录里面的content.xml文件中加上下面两行

#添加到content.xml
<Valve className="com.r.tomcat.session.management.RequestSessionHandlerValve"/>
<Manager className="com.r.tomcat.session.management.RequestSessionManager"/>

参考链接:https://github.com/ran-jit/TomcatClusterRedisSessionManager/wiki

四:shiro实现开发自定义的Shiro的SessionDAO

第一步: 添加shiro需要的资源

第一步:添加依赖
<dependency>
<groupId>org.apache.shiro</groupId> 
 <artifactId>shiro-core</artifactId> 
 <version>1.2.2</version>
</dependency>
<dependency>
 <groupId>org.apache.shiro</groupId>
 <artifactId>shiro-web</artifactId> 
<version>1.2.2</version>
</dependency>
<dependency>
 <groupId>org.apache.shiro</groupId>
 <artifactId>shiro-aspectj</artifactId> 
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId> 
 <artifactId>shiro-ehcache</artifactId>
 <version>1.2.2</version>
</dependency>
<dependency>
 <groupId>org.apache.shiro</groupId> 
 <artifactId>shiro-spring</artifactId> 
 <version>1.2.2</version>
</dependency>
第二步:
在spring-mvc.xml中添加对shiro的filter的配置
 <bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <property name="loginUrl" value="/toLogin"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
 <property name="filterChainDefinitions">
    <value>/jcaptcha* = anon /logout = anon</value>
 </property>
</bean> 
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;

import com.danga.MemCached.MemCachedClient;

public class MySessionDAO extends AbstractSessionDAO{
	private static final int EXPIRE_TIME = 1*60;
	@Autowired
	private MemCachedClient mcc;
	
	public void update(Session session) throws UnknownSessionException {
		mcc.set(session.getId().toString(), session,new Date(EXPIRE_TIME));
	}

	public void delete(Session session) {
		mcc.delete(session.getId().toString());
	}

	public Collection<Session> getActiveSessions() {
		/**
		 * @todo
		 */
		return new ArrayList<Session>();
	}

	@Override
	protected Serializable doCreate(Session session) {
		Serializable sid = this.generateSessionId(session);
		assignSessionId(session, sid);
		
		mcc.add(sid.toString(), session,new Date(EXPIRE_TIME));
		return sid;
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		Session s = (Session)mcc.get(sessionId.toString());
		//计算过期时间,是从最后一次使用开始
		mcc.set(sessionId.toString(),s, new Date(EXPIRE_TIME));
		return s;
	}
}
第四步:
在web.xml中添加对shiroFilter的配置 <filter>

<filter-name>shiroFilter</filter-name> <filter-

class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param>

<param-name>targetFilterLifecycle</param-name> <param-value>true</param-value>

</init-param> </filter> <filter-mapping>

<filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern>

</filter-mapping>

第五步使用自定义的MySessionDAO

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:mongo="http://www.springframework.org/schema/data/mongo"
	xmlns:repository="http://www.springframework.org/schema/data/repository"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository.xsd
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.5.xsd
">
	<bean
		class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
		<property name="staticMethod"
			value="org.apache.shiro.SecurityUtils.setSecurityManager" />
		<property name="arguments" ref="securityManager" />
	</bean>
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="cacheManager" ref="cacheManager" />
		<property name="sessionManager" ref="sessionManager" />
	</bean>
	<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
		<property name="sessionDAO" ref="sessionDAO"></property>
	</bean>
	<bean id="sessionDAO" class="com.sishuok.shiro.MySessionDAO" />
	<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager" />
</beans>

 

五:spring session

如果是springboot就非常简单

添加依赖

<!-- spring session -->
<dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session</artifactId>
</dependency>
<!-- redis -->
<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-redis</artifactId>
</dependency>					

配置application.properties

# spring session使用存储类型
#spring.session.store-type=redis
# spring session刷新模式:默认on-save
#spring.session.redis.flush-mode=on-save
#spring.session.redis.namespace= 
# session超时时间,单位秒
#server.session.timeout=30

#redis
#spring.redis.host=localhost
#spring.redis.port=6379
#spring.redis.password=123456
#spring.redis.database=0
#spring.redis.pool.max-active=8 
#spring.redis.pool.max-idle=8 
#spring.redis.pool.max-wait=-1 
#spring.redis.pool.min-idle=0 
#spring.redis.timeout=0

如果是传统的spring项目请参考:http://blog.csdn.net/u012515742/article/details/54973075

© 著作权归作者所有

共有 人打赏支持
weiliu007
粉丝 14
博文 171
码字总数 84766
作品 0
深圳
程序员
分布式session共享常用的几种方式

tomcat session共享常用的几种方式 1、请求精确定位 粘性会话:session sticky 例如基于访问ip的hash策略,即当前用户的请求都集中定位到一台服务器中,这样单台服务器保存了用户的session登...

啃不动地大坚果
06/14
0
0
浅谈web应用的负载均衡、集群、高可用(HA)解决方案

1、熟悉几个组件 1.1、apache —— 它是Apache软件基金会的一个开放源代码的跨平台的网页服务器,属于老牌的web服务器了,支持基于Ip或者域名的虚拟主机,支持代理服务器,支持安全Socket层(...

stone_
2016/05/04
273
0
浅谈web应用的负载均衡、高可用、群集

1、熟悉几个组件 1.1、apache —— 它是Apache软件基金会的一个开放源代码的跨平台的网页服务器,属于老牌的web服务器了,支持基于Ip或者域名的虚拟主机,支持代理服务器,支持安全Socket层(...

壹休哥
2016/11/06
0
0
分布式学习(4) ---- Spring Session + Redis实现分布式Session共享

单个服务器的应用,Tomcat会将Session保存在本机内存中,但一旦涉及到分布式应用,如何实现不同服务器间的Session共享问题呢? 目前比较主流的方式还是基于分布式缓存Memcached、redis实现,...

KKys
2017/02/07
0
0
关于集群中session共享理解的问题?

最近在研究集群和分布式的实现,感觉非常吃力。 集群是一套完整的系统部署到不同的服务器(tomcat)中,每个服务器中部署的程序都是一样的,通过nginx反向代理就可以根据权重把用户的请求转发...

颖辉小居
2017/02/03
534
6
bboss 会话共享框架 4.0.8 发布

bboss 会话共享4.0.8发布 bboss 会话共享功能特点: 作 用:为应用提供统一会话管理功能,避免集群部署场景下负载切换session丢失问题; 跨域跨应用共享会话并实现SSO功能;解决了会话共享五...

bboss
2015/08/02
3.2K
16
基于MSM实现nginx负载均衡+tomcat集群+memcached(session共享)

Session共享的方案介绍 Session 共享有多种解决方法,常用的有四种:客户端 Cookie 保存、服务器间 Session 同步、使用集群管理 Session(如本文要介绍的Memcached Session Manager) 、把 ...

jaychang
2016/01/20
4.1K
7
session会话-nginx-mysql-tomcat

一、如何保持session会话 目前,为了使web能适应大规模的访问,需要实现应用的集群部署。集群最有效的方案就是负载均衡,而实现负载均衡用户每一个请求都有可能被分配到不固定的服务器上,这...

柴鑫旺
2017/09/11
0
0
bboss session 共享框架 v4.0.9 发布

bboss 会话共享4.0.9发布,4.0.9增加了以下特性: 升级mongodb客户端驱动到mongo-java-driver-3.0.3 支持mongodb最新稳定版本3.0.6(终于可以使用最新的高性能、可伸缩的NoSQL数据存储引擎W...

bboss
2015/09/05
1K
16
分布式web架构中Session管理的方法

分布式架构 单体架构中,Session管理方案是在用户进行登录的时候将Session存放在应用服务器的内存中,由于只有一个应用服务器节点,用户的所有请求都是这个唯一节点进行响应处理,所以能够轻...

刘诗书
2017/11/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

MyBatis源码解读之延迟加载

1. 目的 本文主要解读MyBatis 延迟加载实现原理 2. 延迟加载如何使用 Setting 参数配置 设置参数 描述 有效值 默认值 lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延...

无忌
8分钟前
0
0
javascript 类变量的实现

代码如下: function echo(){ for(let i=0;i<arguments.length;i++) console.log(arguments[i]);}function extend(o, p){for (prop in p) {o[prop] = p[prop]}retur......

backbye
12分钟前
0
2
编程语言对比分析:Python与Java和JavaScript(图)

编程语言对比分析:Python与Java和JavaScript(图): 凭什么说“Python 太慢,Java 太笨拙,我讨厌 JavaScript”?[图] 编程语言生而为何? 我们人类从原始社会就是用语言表达自己,互相沟通...

原创小博客
21分钟前
0
0
Akka构建Reactive应用《one》

看到这Akka的官网,描述使用java或者scala构建响应式,并发和分布式应用更加简单,听着很高级的样子,下面的小字写着消息驱动,但是在quickstart里面又写容错事件驱动,就是这么钻牛角尖。 ...

woshixin
32分钟前
0
0
ffmpeg源码分析 (四)

io_open 承接上一篇,对于avformat_open_input的分析还差其中非常重要的一步,就是io_open,该函数用于打开FFmpeg的输入输出文件。 在init_input中有这么一句 if ((ret = s->io_open(s, &s-...

街角的小丑
34分钟前
0
0
String,StringBuffer ,StringBuilder的区别

不同点 一、基类不同 StringBuffer、StringBuilder 都继承自AbStractStringBuilder,String 直接继承自 Object 2、底层容器“不同” 虽然底层都是字符数组,但是String的是final修饰的不可变...

不开心的时候不要学习
49分钟前
0
0
nodejs 文件操作

写文件code // 加载文件模块var fs = require("fs");var content = 'Hello World, 你好世界!';//params 文件名,内容,编码,回调fs.writeFile('./hello.txt',content,'utf8',function (er......

yanhl
51分钟前
0
0
SpringBoot mybits 查询为0条数据 但是在Navicat 中可以查询到数据

1.页面请求: 数据库查询: 2018-07-16 17:56:25.054 DEBUG 17312 --- [nio-9010-exec-3] c.s.h.m.C.selectSelective : ==> Preparing: select id, card_number, customer_id, customer_nam......

kuchawyz
今天
0
0
译:Self-Modifying cod 和cacheflush

date: 2014-11-26 09:53 翻译自: http://community.arm.com/groups/processors/blog/2010/02/17/caches-and-self-modifying-code Cache处在CPU核心与内存存储器之间,它给我们的感觉是,它具......

我叫半桶水
今天
0
0
Artificial Intelligence Yourself

TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理。Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算,TensorFlow为张量从流...

孟飞阳
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部