一、分布式Session共享方案的由来
客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是 Session。客户端浏览器再次访问时只需要从该 Session 中查找该客户的状态就可以了。
在实际工作中当应用做集群 / 分布式部署时,用户请求会被负载均衡分发到不同 Tomcat 节点,如果每个节点各自维护 Session,就会出现用户频繁登录、状态丢失的问题。
因此需要Session 共享:把所有 Session 统一存储到外部中间件(Redis、Memcached 等),所有应用节点共享同一份 Session 数据。
本文使用Redis实现共享session,所有服务器的session信息都存储到了同一个Redis集群中,即所有的服务都将 Session 的信息存储到 Redis 集群中,无论是对 Session 的注销、更新都会同步到集群中,达到了 Session 共享的目的。
Cookie是服务器写给客户端的文件,也可以称为浏览器缓存。保存在客户端浏览器中,而 Session 保存在服务器上。
二、常见的session集群方案
传统的session由服务器端生成并存储,当应用进行分布式集群部署的时候,如何保证不同服务器上session信息能够共享
两种实现方式:
Session复制
是指session信息会在集群节点之间复制,每个节点服务器上都会有相同的session信息。
优点: 是即使一个节点服务器宕机了,只要还有服务器存活,就不影响用户使用。
缺点: 缺点是node之间通信频繁,响应速度有影响,多并发、高频操作的情况下性能下降比较厉害。
Session共享
基于Memcache/Redis等数据库的session共享。
tomcat自带集群中,提供了session复制,session信息会在各个tomcat中同步,对网络要求较高,session内存消耗影响会很大,对于小集群够用了,大集群还是建议使用redis或者memcache进行session共享。
因此,构建tomcat集群时,可以使用tomcat基于redis的session共享机制。而在通过nginx构建集群时,也涉及session的问题
如下图所示架构:

三、应用环境介绍
1、session应用工具
这里主要介绍一个的方案:redisson,支持最新的JDK和各个版本的tomcat(6/7/8/9/10),官网:https://redisson.org/ 。
redisson是redis官网推荐的java语言实现分布式锁的项目。当然,redisson远不止分布式锁,还包括其他一些分布式结构。例如,分布式应用,分布式缓存,分布式回话管理,分布式服务(任务,延迟任务,执行器),分布式redis客户端等。而我们这里要使用的是redisson提供的Tomcat Session Manager功能。
Tomcat session共享的github地址为:
https://github.com/redisson/redisson/tree/master/redisson-tomcat
2、环境准备
首先说明下此案例的应用环境:
(1)三台物理机或虚拟机,使用CentOS 7系统(192.168.38.137、192.168.38.138、192.168.38.139)
(2)redis7.x版本
(3)JDK1.8版本
(4)tomcat9.x版本
(5)nginx1.23版本
其中,192.168.38.137服务器安装redis和tomcat1,192.168.38.138安装tomcat2.,192.168.38.139安装nginx,通过nginx的负载均衡功能,实现tomcat1和tomcat2的负载均衡,进而判断两个tomcat实例是否实现了session共享。
四、nginx+tomcat+redis部署过程
整个部署过程很简单,分别三个步骤,分别介绍如下:
1、redis安装部署
redis安装部署比较简单,首先从https://redis.io 下载最新版本的redis,这里下载的是redis7.x版本,然后编译即可,过程如下:
[root@localhost ~]# tar zxvf redis-7.0.9.tar.gz
[root@localhost ~]# cd redis-7.0.9
[root@localhost redis-7.0.9]# make
[root@localhost redis-7.0.9]# make install
[root@localhost redis-7.0.9]# cp redis.conf /etc #拷贝配置文件到/etc目录下
执行演示:
安装成功入下图所示

拷贝配置文件到/etc目录下
![]()
2、配置redis并启动
打开redis配置文件/etc/redis.conf,修改两个配置项的值为如下内容:
vim /etc/redis.conf
bind 0.0.0.0
daemonize yes
protected-mode no
执行演示:
生产环境一定要在redis.conf设置强密码,同时bind限定只能是你的tomcat服务器ip,现在的配置是为了实验方便,直接开放了所有 IP 访问。
![]()
开启后台运行
![]()
关闭保护模式
![]()
最后,启动redis服务即可:
[root@localhost ~]# /usr/local/bin/redis-server /etc/redis.conf
检查redis监听的是不是0.0.0.0:6379

3、tomcat安装部署
部署tomcat之前,需要先安装JDK,这里选择JDK1.8版本,从oracle官网下载linux-64版本的JDK,下载时,选择适合自己机器运行环境的版本,oracle官网提供的JDK都是二进制版本的,因此,JDK的安装非常简单,只需将下载下来的程序包解压到相应的目录即可。安装过程如下:
[root@localhost ~]# mkdir /usr/java
[root@localhost ~]# tar -zxvf jdk-8u201-linux-x64.tar.gz -C /usr/java/
这里我们将JDK安装到了/usr/java/目录下。接着,要让程序能够识别JDK路径,还需要设置JDK的环境变量,这里我们将JDK环境变量设置到/etc/profile文件中。添加如下内容到/etc/profile文件最后:
export JAVA_HOME=/usr/java/jdk1.8.0_201
export PATH=$PATH:$JAVA_HOME/bin
exportCLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:$CLASSPATH
然后执行如下命令让设置生效:
[root@localhost ~]# source /etc/profile
最后,在Shell提示符中执行“java -version”命令,如果显示如下结果,说明安装成功:
[root@localhost ~]# java -version
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
JDK部署成功后,就可以部署tomcat了,tomcat的安装很简单,从http://tomcat.apache.org/ 下载最新的tomcat,然后解压即可,这里下载tomcat9版本,安装到/usr/local/目录下,执行如下操作:
[root@localhost ~]# tar zxvf apache-tomcat-9.0.72.tar.gz -C /usr/local
[root@localhost ~]# mv /usr/local/apache-tomcat-9.0.72 /usr/local/tomcat9
这样,tomcat也安装完成了。
执行演示:
从oracle官网下载linux-64版本的JDK1.8压缩包

将压缩包解压到/usr/java目录下,该目录需要先创建
![]()
然后配置java的环境变量,配置完成后使用source加载配置
输入java -version如下图输出则安装成功

现在我们就可以安装tomcat了,下载后将压缩包解压就行
同理我们在另外一台虚拟机安装tomcat
4、tomcat与redis整合实现session共享
接下来就是配置tomcat了,要配置tomcat和redis整合,实现session管理,需要几个步骤。
(1)、部署jar包
根据github上的说明 ,需要下载两个jar包,根据我们的环境,分别是redisson-all-3.20.0.jar和redisson-tomcat-9-3.20.0.jar,这两个jar包都可以从https://github.com/redisson/redisson/tree/master/redisson-tomcat 下载。
在最新的redisson版本中,还需要另一个依赖jar包fst,我这里下载的是fst-2.57.jar,如果没有此jar包,tomcat启动会出错,将下载下来的jar包放到$TOMCAT_BASE/lib目录下即可,我们这里的路径是/usr/local/tomcat9/lib。
(2)、增加RedissonSessionManager配置
这个步骤是在tomcat的配置文件$TOMCAT_BASE/conf/context.xml中,添加如下配置:
<Manager className="org.redisson.tomcat.RedissonSessionManager"
configPath="${catalina.base}/conf/redisson.json"
readMode="REDIS"
updateMode="DEFAULT"/>
其中,{catalina.base}/conf/redisson.json文件内容如下:
{
"singleServerConfig":{
"idleConnectionTimeout":10000,
"connectTimeout":10000,
"timeout":3000,
"retryAttempts":3,
"retryInterval":1500,
"password":null,
"subscriptionsPerConnection":5,
"clientName":null,
"address": "redis://192.168.38.137:6379",
"subscriptionConnectionMinimumIdleSize":1,
"subscriptionConnectionPoolSize":50,
"connectionMinimumIdleSize":32,
"connectionPoolSize":64,
"database":0,
"dnsMonitoringInterval":5000
},
"threads":0,
"nettyThreads":0,
"codec":{
"class":"org.redisson.codec.FstCodec"
},
"transportMode":"NIO"
}
需要注意这里面的"address"一项的值,如果tomcat和redis安装在一起,可以写成127.0.0.1:6379,如果redis在独立的一台机器上,就写redis所在机器的IP地址。这里redis所在的IP为192.168.38.137,所以上面就写这个地址即可。
到此为止,tomcat与redis的互联配置完成。
5、测试获取session
在tomcat的$TOMCAT_BASE/webapps/ROOT目录下创建一个testsession.jsp文件,内容如下:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
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>tomcat1</title>
</head>
<body>
<center><h1>tomcat1</h1></center>
<center>
<h3>sessionId:</h3><%=session.getId()%>
<h3>session创建时间:</h3><%=session.getCreationTime()%>
<center>
</body>
</html>
接着,启动tomcat服务,执行如下命令:
[root@localhost ~]#/usr/local/tomcat9/bin/startup.sh
启动tomcat后,在浏览器访问:http://192.168.38.137:8080/testsession.jsp, 如下图所示:

然后,登录redis客户端,查看key信息,如下图所示:
[root@localhost ~]#redis-cli
127.0.0.1:6379> keys *
1) "redisson:tomcat_session:3C9CCFDD65022303DDCEDB1180A1703A"
127.0.0.1:6379>

可以看到,redis里面已经生成了session信息。
6、部署第二个tomcat实例
上面已经部署好了第一台tomcat实例tomcat1,接着在192.168.38.138上部署另一个tomcat实例tomcat2,最简单的部署方法是直接拷贝第一个tomcat1实例到192.168.38.138上对应的位置即可。
为了两个tomcat实例进行区分,这里需要修改testsession.jsp文件中的一些标识信息,修改后的内容如下:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
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>tomcat2</title>
</head>
<body>
<center><h1>tomcat2</h1></center>
<center>
<h3>sessionId:</h3><%=session.getId()%>
<h3>session创建时间:</h3><%=session.getCreationTime()%>
<center>
</body>
</html>
这里主要是将文件中的tomcat1修改为了tomcat2,最后,还需要在192.168.38.138上安装和配置JDK,这个上面已经做了介绍,这里不再说明。
所有修改完成后,启动tomcat服务,然后访问http://192.168.38.138:8080/testsession.jsp, 如下图所示:

可以看到,通过192.168.38.137和192.168.38.138访问testsession.jsp页面得到的session信息是不一样的。这是正常的。
7、部署nginx负载均衡
根据上面的定义,nginx是安装在192.168.38.139服务器上,从nginx官网http://nginx.org/ 下载最新的nginx版本,这里是nginx-1.23版本,然后进行编译安装,过程如下:
[root@centos ~]# yum -y install zlib pcre pcre-devel openssl openssl-devel
[root@centos ~]# useradd -s /sbin/nologin www
[root@centos ~]#tar zxvf nginx-1.23.3.tar.gz
[root@centos ~]#cd nginx-1.23.3
[root@centos nginx-1.23.3]# ./configure \
--user=www \
--group=www \
--prefix=/usr/local/nginx \
--sbin-path=/usr/local/nginx/sbin/nginx \
--conf-path=/usr/local/nginx/conf/nginx.conf \
--error-log-path=/usr/local/nginx/logs/error.log \
--http-log-path=/usr/local/nginx/logs/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/lock/subsys/nginx \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_gzip_static_module \
--with-pcre
[root@centos nginx-1.23.3]# make
[root@centos nginx-1.23.3]# make install
这样,nginx就安装完成了。接下来,就是配置nginx了,打开nginx配置文件nginx.conf,重点修改如下部分内容:
user www;
worker_processes 8;
events {
worker_connections 65536;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream tomcat {
server 192.168.38.137:8080 weight=1;
server 192.168.38.138:8080 weight=1;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://tomcat;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
最后,启动nginx即可:
[root@centos nginx-1.23.3]# /usr/local/nginx/sbin/nginx
五、测试nginx+tomcat+redis的session共享功能
nginx配置完成后,就可以通过http://192.168.38.139/testsession.jsp 访问两个tomcat实例了,如下图所示:


可以看到,如果不停刷新这个页面的话,会在两个tomcat实例之间来回轮询切换,但session值并不发生变化,这说明两个tomcat实例都共享了redis里面存储的session信息,

也就是实现了nginx+tomcat+redis的session共享功能。


2538

被折叠的 条评论
为什么被折叠?



