文档章节

Tomcat基于MSM+Memcached实现Session共享

eddy_linux
 eddy_linux
发布于 2015/11/16 14:37
字数 1751
阅读 56
收藏 5
点赞 0
评论 0

前言

在Tomcat集群中,当一个节点出现故障,其他节点该如何接管故障节点的Session信息呢?本文带来的解决方案是基于MSM+Memcached实现Session共享。

相关介绍

MSM

MSM–Memcached Session Manager是一个高可用的Tomcat Session共享解决方案,除了可以从本机内存快速读取Session信息(仅针对黏性Session)外,同时可使用Memcached存取Session,以实现高可用。

工作原理


Sticky Session(黏性) 模式下的工作原理

#Tomcat本地Session为主Session,Memcached 中的Session为备Session

安装在Tomcat上的MSM使用本机内存保存Session,当一个请求执行完毕之后,如果对应的Session在本地不存在(即某用户的第一次请求),则将该Session复制一份至Memcached;当该Session的下一个请求到达时,会使用Tomcat的本地Session,请求处理结束之后,Session的变化会同步更新到 Memcached,保证数据一致。

当集群中的一个Tomcat挂掉,下一次请求会被路由到其他Tomcat上。负责处理此此请求的Tomcat并不清楚Session信息,于是从Memcached查找该Session,更新该Session并将其保存至本机。此次请求结束,Session被修改,送回Memcached备份。


Non-sticky Session (非黏性)模式下的工作原理

#Tomcat本地Session为中转Session,Memcached为主备Session

收到请求,加载备Session至本地容器,若备Session加载失败则从主Session加载

请求处理结束之后,Session的变化会同步更新到Memcached,并清除Tomcat本地Session

实现过程

实验拓扑

#系统环境:CentOS6.6

nginx安装配置

解决依赖关系
[root@scholar ~]# yum groupinstall "Development Tools" "Server Platform Deveopment" -y
[root@scholar ~]# yum install openssl-devel pcre-devel -y
[root@scholar ~]# groupadd -r nginx
[root@scholar ~]# useradd -r -g nginx nginx
[root@scholar ~]# tar xf nginx-1.6.3.tar.gz
[root@scholar ~]# cd nginx-1.6.3
[root@scholar nginx-1.6.3]# ./configure \
> --prefix=/usr/local/nginx \
> --sbin-path=/usr/sbin/nginx \
> --conf-path=/etc/nginx/nginx.conf \
> --error-log-path=/var/log/nginx/error.log \
> --http-log-path=/var/log/nginx/access.log \
> --pid-path=/var/run/nginx/nginx.pid \
> --lock-path=/var/lock/nginx.lock \
> --user=nginx \
> --group=nginx \
> --with-http_ssl_module \
> --with-http_flv_module \
> --with-http_stub_status_module \
> --with-http_gzip_static_module \
> --http-client-body-temp-path=/usr/local/nginx/client/ \
> --http-proxy-temp-path=/usr/local/nginx/proxy/ \
> --http-fastcgi-temp-path=/usr/local/nginx/fcgi/ \
> --http-uwsgi-temp-path=/usr/local/nginx/uwsgi \
> --http-scgi-temp-path=/usr/local/nginx/scgi \
> --with-pcre
[root@scholar nginx-1.6.3]# make && make install
为nginx提供SysV init脚本
[root@scholar ~]# vim /etc/rc.d/init.d/nginx
#新建文件/etc/rc.d/init.d/nginx,内容如下:
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig: - 85 15
# description: Nginx is an HTTP(S) server, HTTP(S) reverse \
# proxy and IMAP/POP3 proxy server
# processname: nginx
# config: /etc/nginx/nginx.conf
# config: /etc/sysconfig/nginx
# pidfile: /var/run/nginx.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
nginx="/usr/sbin/nginx"
prog=$(basename $nginx)
NGINX_CONF_FILE="/etc/nginx/nginx.conf"
[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx
lockfile=/var/lock/subsys/nginx
make_dirs() {
# make required directories
user=`nginx -V 2>&1 | grep "configure arguments:" | sed's/[^*]*--user=\([^ ]*\).*/\1/g' -`
options=`$nginx -V 2>&1 | grep 'configure arguments:'`
for opt in $options; do
if [ `echo $opt | grep '.*-temp-path'` ]; then
value=`echo $opt | cut -d "=" -f 2`
if [ ! -d "$value" ]; then
# echo "creating" $value
mkdir -p $value && chown -R $user $value
fi
fi
done
}
start() {
[ -x $nginx ] || exit 5
[ -f $NGINX_CONF_FILE ] || exit 6
make_dirs
echo -n $"Starting $prog: "
daemon $nginx -c $NGINX_CONF_FILE
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
killproc $prog -QUIT
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
configtest || return $?
stop
sleep 1
start
}
reload() {
configtest || return $?
echo -n $"Reloading $prog: "
killproc $nginx -HUP
RETVAL=$?
echo
}
force_reload() {
restart
}
configtest() {
$nginx -t -c $NGINX_CONF_FILE
}
rh_status() {
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-
reload|configtest}"
exit 2
esac

配置nginx
[root@scholar ~]# vim /etc/nginx/nginx.conf
upstream www.scholar.com {
server 172.16.10.123:8080;
server 172.16.10.124:8080;
}
server {
listen 80;
server_name www.scholar.com;
location / {
proxy_pass http://www.scholar.com;
index index.jsp index.html index.htm;
}
}
[root@scholar ~]# service nginx start
Starting nginx: [ OK ]
测试页面
[root@node1 local]# cd tomcat/webapps/
[root@node1 webapps]# mkdir -pv test/WEB-INF/{classes,lib}
[root@node1 webapps]# cd test/
[root@node1 test]# vim index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.scholar.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("scholar.com","scholar.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
#另一个节点将TomcatA替换为TomcatB,颜色设为蓝色
[root@node1 test]# service tomcat start

此时Session信息并不一致,接下来我们通过配置MSM实现Session共享

memcached安装

#解决依赖关系
[root@scholar ~]# yum groupinstall "Development Tools" "Server Platform Deveopment" -y
#安装libevent
#memcached依赖于libevent API,因此要事先安装之
[root@scholar ~]# tar xf libevent-2.0.22-stable.tar.gz
[root@scholar ~]# cd libevent-2.0.22-stable
[root@scholar libevent-2.0.22-stable]# ./configure --prefix=/usr/local/libevent
[root@scholar libevent-2.0.22-stable]# make && make install
[root@scholar ~]# echo "/usr/local/libevent/lib" > /etc/ld.so.conf.d/libevent.conf
[root@scholar ~]# ldconfig
#安装配置memcached
[root@scholar ~]# tar xf memcached-1.4.24.tar.tar
[root@scholar ~]# cd memcached-1.4.24
[root@scholar memcached-1.4.24]# ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
[root@scholar memcached-1.4.24]# make && make install

[root@scholar ~]# vim /etc/init.d/memcached
#!/bin/bash
#
# Init file for memcached
#
# chkconfig: - 86 14
# description: Distributed memory caching daemon
#
# processname: memcached
# config: /etc/sysconfig/memcached
. /etc/rc.d/init.d/functions
## Default variables
PORT="11211"
USER="nobody"
MAXCONN="1024"
CACHESIZE="64"
RETVAL=0
prog="/usr/local/memcached/bin/memcached"
desc="Distributed memory caching"
lockfile="/var/lock/subsys/memcached"
start() {
echo -n $"Starting $desc (memcached): "
daemon $prog -d -p $PORT -u $USER -c $MAXCONN -m $CACHESIZE
RETVAL=$?
[ $RETVAL -eq 0 ] && success && touch $lockfile || failure
echo
return $RETVAL
}
stop() {
echo -n $"Shutting down $desc (memcached): "
killproc $prog
RETVAL=$?
[ $RETVAL -eq 0 ] && success && rm -f $lockfile || failure
echo
return $RETVAL
}
restart() {
stop
start
}
reload() {
echo -n $"Reloading $desc ($prog): "
killproc $prog -HUP
RETVAL=$?
[ $RETVAL -eq 0 ] && success || failure
echo
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
condrestart)
[ -e $lockfile ] && restart
RETVAL=$?
;;
reload)
reload
;;
status)
status $prog
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|restart|condrestart|status}"
RETVAL=1
esac
exit $RETVAL

将所需jar包放入各tomcat节点的tomcat安装目录下的lib目录中
[root@node1 ~]# cd msm/
[root@node1 msm]# ls
javolution-5.4.3.1.jar msm-javolution-serializer-1.8.1.jar
memcached-session-manager-1.8.1.jar spymemcached-2.10.2.jar
memcached-session-manager-tc7-1.8.1.jar
[root@node1 msm]# cp * /usr/local/tomcat/lib/
#各tomcat节点都需执行以上操作
[root@node1 msm]# vim /usr/local/tomcat/conf/server.xml
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JasperListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="www.scholar.com" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="/test" docBase="/usr/local/tomcat/webapps/test/" reloadable="true">
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.16.10.126:11211,n2:172.16.10.212:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.Javolu
tionTranscoderFactory"
/>
</Context>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="scholar_access_log." suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="scholar_access_log." suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

访问测试

由此可见,Session共享已实现,下面我们模拟TomcatB节点故障,看一下Session是否会发生改变

虽然因为TomcatB故障,导致用户请求被调度到了TomcatA节点上,但Session ID并未发生改变,即Session集群内的所有节点都保存有全局的Session信息,很好的实现了用户访问的不中断

当n2(memcached)节点发生故障,Session信息会不会转移到其他memcached节点呢,我们来试一下

Session已转移到n1上,而且Session ID并未发生改变,至此,Tomcat基于MSM+Memcached实现Session共享目的已实现

The end

Tomcat基于MSM+Memcached实现Session共享实验就说到这里了


本文转载自:http://mp.weixin.qq.com/s?__biz=MzA3OTgyMDcwNg==&mid=209983098&idx=1&sn=279f7c1a6c768abeca53ff5aa...

共有 人打赏支持
eddy_linux
粉丝 18
博文 135
码字总数 188789
作品 0
成都
程序员
分布式集群系统下的高可用session解决方案

目前,为了使web能适应大规模的访问,需要实现应用的集群部署. 而实现集群部署首先要解决session的统一,即需要实现session的共享机制。 目前,在集群系统下实现session统一的有如下几种方案:...

凯文加内特 ⋅ 2015/03/19 ⋅ 0

session会话-nginx-mysql-tomcat

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

柴鑫旺 ⋅ 2017/09/11 ⋅ 0

Nginx反向代理,负载均衡+Tomcat实现Session共享

Nginx反向代理,负载均衡+Tomcat实现Session共享 防伪码:学而不思则罔,思而不学则殆。 作者:何小帅 博客URL:http://hexiaoshuai.blog.51cto.com 一、如何保持session会话 目前,为了使w...

何小帅 ⋅ 2017/01/14 ⋅ 0

分布式session共享常用的几种方式

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

啃不动地大坚果 ⋅ 06/14 ⋅ 0

分布式学习(4) ---- Spring Session + Redis实现分布式Session共享

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

KKys ⋅ 2017/02/07 ⋅ 0

关于扩展Tomcat的Session存取机制的思考

在开发大规模网站程序时,一般会让开发人员尽量采用Cookie而非Session来存 储一些状态相关的数据,例如用户登录信息等等。原因是不推荐做Session复制,而多个应用服务器之间为了共享Session...

红薯 ⋅ 2008/10/05 ⋅ 5

集群下的session共享总结及问题

最近公司需要实现websphere集群的session共享,websphere集群本身支持共享,但是添加、删除节点还是需要重启服务才行(如果不是,请指正)。最近一直在骚扰@红薯 ,希望了解OSC的实现,现在也...

人头马没面 ⋅ 2012/12/08 ⋅ 14

redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)

一、redis介绍 redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型...

何小帅 ⋅ 2017/03/26 ⋅ 0

分布式Session集中存储方案

在文章分布式web架构中Session管理的方法中讲了分布式Session管理的4种办法,其中第4种的Session集中存储实际运用比较广泛,下面来讲解这种的实现方案。 目前常用的Session集中管理方案有两种...

刘诗书 ⋅ 2017/11/23 ⋅ 0

基于MSM实现nginx负载均衡+tomcat集群+memcached(session共享)

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

jaychang ⋅ 2016/01/20 ⋅ 7

没有更多内容

加载失败,请刷新页面

加载更多

下一页

win环境下jdk7与jdk8共存配置

1.jdk安装包 jdk安装包 安装步骤略 2.jdk等配置文件修改 在安装JDK1.8时(本机先安装jdk1.7再安装的jdk1.8),会将java.exe、javaw.exe、javaws.exe三个文件copy到了C:\Windows\System32,这...

泉天下 ⋅ 15分钟前 ⋅ 0

windows profesional 2017 build problem

.net framework .... https://stackoverflow.com/questions/43330915/could-not-load-file-or-assembly-microsoft-build-frameworkvs-2017...

机油战士 ⋅ 49分钟前 ⋅ 0

python3中报错的解决方法(长期更新)

1、ImportError: No module named ‘DjangoUeditor’ 出错原因:安装DjangoUeditor库适用于python2,需要下载适用python3的 下载地址:https://github.com/twz915/DjangoUeditor3 2、python3......

xiaoge2016 ⋅ 54分钟前 ⋅ 0

数据结构与算法之双向链表

一、双向链表 1.双向链表的结点结构 typedef struct DualNode{ ElemType data; struct DualNode *prior; // 前驱结点 struct DualNode *next; // 后继结点}DualNode, *DuL...

aibinxiao ⋅ 今天 ⋅ 0

五大最核心的大数据技术

大数据技术有5个核心部分,数据采集、数据存储、数据清洗、数据挖掘、数据可视化。关于这5个部分,有哪些核心技术?这些技术有哪些潜在价值?看完今天的文章就知道了。 大数据学习群:7165810...

董黎明 ⋅ 今天 ⋅ 0

PhpStorm 头部注释、类注释和函数注释的设置

首先,PhpStorm中文件、类、函数等注释的设置在:setting-》Editor-》FIle and Code Template-》Includes下设置即可,其中方法的默认是这样的: /**${PARAM_DOC}#if (${TYPE_HINT} != "v...

nsns ⋅ 今天 ⋅ 0

spring.net AOP

http://www.springframework.net/doc-latest/reference/html/aop-quickstart.html https://www.cnblogs.com/wujy/archive/2013/04/06/3003120.html AOP系列(一)——ProxyFactoryObject 显式创......

whoisliang ⋅ 今天 ⋅ 0

【HAVENT原创】创建 Dockerfile 生成新的镜像,并发布到 DockerHub

注意:Win7 与 Win10 的版本存在差异,Win7 版本使用 Docker Quickstart Terminal 进入控制台,Win10下面直接用管理员权限打开控制台或者 PowerShell 即可;另外 Win7 下面只能访问 C盘,/ap...

HAVENT ⋅ 今天 ⋅ 0

pom.xml出现web.xml is missing ...解决方案

提示信息应该能看懂。也就是缺少了web.xml文件,<failOnMissingWebXml>被设置成true了。 搜索了一下,Stack Overflow上的答案解决了问题,分享一下。 目前被顶次数最多的回答原文如下: This...

源哥L ⋅ 今天 ⋅ 0

js时间戳与日期格式之间相互转换

1. 将时间戳转换成日期格式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // 简单的一句代码 var date = new Date(时间戳); //获取一个时间对象 /** 1. 下面是获取时间日期的方法,需要什么样的格式自己...

Jack088 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部