Nginx+Tomcat集群Redis共享session方案

一、Session集群方案

1.1、分布式Session共享方案的由来

**客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是 Session。**客户端浏览器再次访问时只需要从该 Session 中查找该客户的状态就可以了。

在实际⼯作中我们建议使⽤外部的缓存设备来共享 Session,避免单个服务器节点挂掉⽽影响服务,共享数据都会放到外部缓存容器中【使⽤Redis实现共享session,所有服务器的session信息都存储到了同⼀个Redis集群中,即所有的服务都将 Session 的信息存储到 Redis 集群中,⽆论是对 Session 的注销、更新都会同步到集群中,达成 Session 共享的⽬的】。

Cookie是服务器写给客户端的⽂件,也可以称为浏览器缓存。保存在客户端浏览器中,而 Session 保存在服务器上。

1.2、常见的Session集群方案

传统的session由服务器端⽣成并存储,当应⽤进⾏分布式集群部署的时候,如何保证不同服务器上session信息能够共享呢?有两种实现方式:

《1》不同服务器上session数据进⾏复制。
《2》session集中存储(session共享)(redis,memcached,hbase等)。

|--------|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 序号 | Session信息共享方案 | 说明 |
| 1 | Session复制 | 是指session信息会在集群节点之间复制,每个节点服务器上都会有相同的session信息。 |
| 1 | Session复制 | 优点【是即使⼀个节点服务器宕机了,只要还有服务器存活,就不影响⽤户使⽤】。 |
| 1 | Session复制 | 缺点【是node之间通信频繁,响应速度有影响,多并发、⾼频操作的情况下性能下降⽐较厉害】。 |
| |||
| 2 | Session共享 | 是指基于Memcache/Redis等数据库的session共享。 |
| 2 | Session共享 | tomcat⾃带集群中,提供了session复制,session信息会在各个tomcat中同步,对⽹络要求较⾼, session内存消耗影响会很大,对于小集群够用了,大集群还是建议使⽤redis或者memcache进行 session共享。 因此,构建tomcat集群时,可以使⽤tomcat基于redis的session共享机制。⽽在通过nginx构建集群时,也涉及session的问题。架构设计如下图所示: |
| 2 | Session共享 | 在nginx的集群架构下,可根据设置的nginx负载均衡算法的不同,session的实现机制也不相【如:轮询(默认),指定权重,fair(第三⽅),url_hash(第三⽅)】负载算法时,集群各个节点之间必须通过session共享来实现。 要避开session问题,可以使⽤nginx的ip_hash算法,此算法将⽤户的请求统⼀发送到同⼀个节点服务器上,如不考虑节点服务器宕机的情况,可不考虑session问题。但是,节点服务器宕机后,用户需要关掉浏览器从新打开登录才能恢复正常,这样体验会变得很差。因此,session共享在集群架构中有很大的用途。 |
[常见的Session集群方案]

1.3、应用环境准备

|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 序号 | 说明 |
| 1 | 由于客户要使用Tomcat集群,因此,需要解决session共享的问题。在网上有很多解决方案,(如:通过Memcached来实现,通过Redis来实现的)很多人都是通过jcoleman【https://github.com/jcoleman/tomcat-redis-session-manager】的redis解决方案,但是此方案仅支持tomcat6和7,若要支持tomcat8或9需要修改代码,然后打包部署,非常麻烦。 因此【强烈不推荐此种方案】。 |
| 2 | redisson,⽀持最新的JDK和各个版本的tomcat(6/7/8/9/10/11),官⽹:https://redisson.org/ 。 **redisson是redis官⽹推荐的java语言实现分布式锁的项目。**当然,redisson远不止分布式锁,还包括其他⼀些分布式结构。例如,分布式应⽤,分布式缓存,分布式回话管理,分布式服务(任务,延迟任务,执行器),分布式redis客户端等。⽽我们这⾥要使⽤的是redisson提供的Tomcat SessionManager功能。 Tomcat session共享的github地址为【https://github.com/redisson/redisson/tree/master/redisson-tomcat】 对应的资源包下载地址是【Web Session Management - Redisson Reference Guide】 |
[Session应用工具]

|--------|-------------------------------------------------------------------------|
| 序号 | 应用环境准备内容 |
| 1 | 三台物理机或虚拟机,使⽤RHEL9/Almalinux9.1系统(192.168.1.9、192.168.1.36、192.168.1.37) |
| 2 | Redis7.x版本 |
| 3 | JDK1.8版本 |
| 4 | Tomcat9.x版本 |
| 5 | Nginx1.28版本 |
| 192.168.1.36服务器安装【redis】和【tomcat1】,192.168.1.37安装【tomcat2】,192.168.1.9安装【Nginx】,通过nginx的负载均衡功能,实现tomcat1和tomcat2的负载均衡,进而判断两个tomcat实例是否实现了session共享。 ||
[应用环境准备]

二、Nginx+Tomcat+Redis部署过程

2.1、Redis的安装部署

在192.168.1.36服务器上安装redis的部署流程:

bash 复制代码
#在Linux中下载redis源码包进行安装部署流程

#1-进入【/data】目录
cd /data

#2-下载【7.4.5】版本的redis源码包,redis源码地址【https://github.com/redis/redis】
wget https://github.com/redis/redis/archive/refs/tags/7.4.5.tar.gz

#3-解压下载好的源码包
tar -zxvf 7.4.5.tar.gz

#4-进入redis目录下
cd redis-7.4.5/

#5-编译redis和测试
make
make test

#6-安装redis
make install

#7-拷⻉配置⽂件到/etc⽬录下
cp redis.conf /etc

#8-修改/etc/redis.conf配置文件
bind 127.0.0.1 192.168.1.36 #绑定0.0.0.0表示可以远程或本地连接,且不受IP限制(也可以绑定多个ip,如:我这里的【127.0.0.1】是本机回环地址【192.168.1.36】是网卡地址)          
port 6379                   #默认端口,可以改成别的端口
protected-mode yes          #修改为yes,开启保护模式,默认是yes
daemonize yes               #守护进程设置为yes

#9-设置redis的用户名和密码(有两种方式)
#方法一:直接修改/etc/redis.conf配置文件的【#requirepass foobared】内容修改为【requirepass Qzsd43561】(Qzsd43561是密码,可以根据自己的需要设置)

#方法二:在服务器运行【redis-cli】客户端连接上redis-server后使用ACL创建用户密码并指定权限(如:创建创建一个名为【ck】的用户,密码为【Qzsd43561】,并授予ck用户所有权限命令【ACL SETUSER ck on >Qzsd43561 ~* +@all】)

#10-查找到redis-server所在路径并启动
whereis redis-server
/usr/local/bin/redis-server /etc/redis.conf

#11-永久放开防火墙的6379端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-port

Linux中下载安装部署Redis7.4.5------并设置用户名、密码及其授权的保姆级教程文章浏览阅读17次。本文主要是关于在Linux中【下载Redis的源码进行编译、安装、部署、开机自启】的详细操作流程及其遇到的问题和对应的详细解决步骤及其最后的【下载安装第三方Redis可视化管理工具】https://blog.csdn.net/xiaochenXIHUA/article/details/151261564

2.2、Tomcat安装部署

在192.168.1.36、192.168.1.37服务器上按照如下步骤安装Tomcat的部署流程:

2.2.1、下载安装配置JDK1.8

bash 复制代码
#在Linux服务器上安装Tomcat步骤流程

#1-安装JDK1.8版本(即:将下载好的JDK1.8压缩包文件上传到Linux服务器的/data路径上)
yum install lrzsz -y
cd /data

#2-解压JDK压缩包到指定路径
mkdir -p /usr/java
tar -zxvf jdk-8u201-linux-x64.tar.gz -C /usr/java

#3-设置JDK的环境变量(这样可以让程序能够识别到JDK【即:在/etc/profile文件中添加JAVA变量】)
vi /etc/profile
export JAVA_HOME=/usr/java/jdk1.8.0_201
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:$CLASSPATH

#4-让设置的JDK环境变量生效
source /etc/profile

#5-验证java是否配置成功(若执行查询java版本的命令后显示对应的版本信息则表示成功,否则失败)
java -version

2.2.2、下载安装Tomcat

bash 复制代码
#1-到Tomcat的官网下载Tomcat9的最新版二进制压缩包
https://tomcat.apache.org/download-90.cgi

#2-将下载好的tomcat9压缩包上传到Linux的/data目录中
yum install lrzsz -y
cd /data
rz

#3-将tomcat9压缩包解压到/usr/local/tomcat9目录中
mkdir -p /usr/local/tomcat9
tar -zxvf apache-tomcat-9.0.109.tar.gz -C /usr/local/tomcat9/

到这里表示Tomcat安装完成。

2.2.3、Tomcat与Redis整合实现Session共享

根据【Web 会话管理 - Redisson 参考指南】文档说明,需要下载两个jar包,根据我们的环境,分别是【redisson-all-3.50.0.jar】和【redisson-tomcat-9-3.50.0.jar】。在最新的redisson版本中,还需要另⼀个依赖jar包fst,我这里下载的是fst-2.57.jar,若没有此jar包,tomcat启动会出错,将下载下来的这三个jar包放到$TOMCAT_BASE/lib⽬录下即可,我这里的路径是【/usr/local/tomcat9/apache-tomcat-9.0.109/lib】。

bash 复制代码
#1-下载Session共享使用Tomcat与Redis结合所需的jar包
https://repo1.maven.org/maven2/org/redisson/redisson-all/3.50.0/redisson-all-3.50.0.jar
https://repo1.maven.org/maven2/org/redisson/redisson-tomcat-9/3.50.0/redisson-tomcat-9-3.50.0.jar
https://github.com/RuedigerMoeller/fast-serialization/releases

#2-将这三个jar包上传到tomcat的lib目录中
cd /usr/local/tomcat9/apache-tomcat-9.0.109/lib


#3-增加RedissonSessionManager配置(即:在在tomcat的配置⽂件$TOMCAT_BASE/conf/context.xml中添加【注意:必须要添加在<Context></Context>之间】)
cd /usr/local/tomcat9/apache-tomcat-9.0.109/conf
vi context.xml 

    <Manager className="org.redisson.tomcat.RedissonSessionManager"
                configPath="${catalina.base}/conf/redisson.json" readMode="REDIS" updateMode="DEFAULT"/>

#4-在tomcat的conf配置文件夹下新建【redisson.json】文件并填写配置内容()
cd /usr/local/tomcat9/apache-tomcat-9.0.109/conf
vi redisson.json

{
 "singleServerConfig":{
  "idleConnectionTimeout":10000,
  "connectTimeout":10000,
  "timeout":3000,
  "retryAttempts":3,
  "retryInterval":1500,
  "password":null,
  "subscriptionsPerConnection":5,
  "clientName":null,
  #这里redis后的IP地址与端口号需要根据自己的服务器IP和端口号设置
  "address": "redis://192.168.1.36:6379",
  #设置Redis的用户名
  "username":"ck",
  #设置Redis的密码
  "password":"Qzsd43561",
  "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.1.36,所以上⾯就写这个地址即可【到此为⽌,tomcat与redis的互联配置完成】。

2.2.4、测试获取session

在tomcat的$TOMCAT_BASE/webapps/ROOT⽬录下创建⼀个testsession.jsp⽂件

bash 复制代码
#1-在tomcat的$TOMCAT_BASE/webapps/ROOT⽬录下创建⼀个testsession.jsp⽂件且内容如下
cd /usr/local/tomcat9/apache-tomcat-9.0.109/webapps/ROOT/
vi 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>

#2-启动tomcat9
/usr/local/tomcat9/apache-tomcat-9.0.109/bin/startup.sh 

#3-检查tomcat的启动进程及其对应的日志信息(日志信息里面不能有错误,否则就需要检查了)
ps -ef | grep java
tail -f /usr/local/tomcat9/apache-tomcat-9.0.109/logs/catalina.out

#4-永久放开tomcat的8080端口
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-port

#5-在浏览器输入本服务器的IP:8080(如:192.168.1.36:8080)查看是否可以看到tomcat的页面信息

#6-测试Tomcat结合Session的效果(在浏览器输入本服务器的IP:8080(如:192.168.1.36:8080/testsession.jsp)查看是否可以看到正常的信息显示页面)

#7-在本服务器上查看redis里面是否正确记录了测试界面显示的seesionid数据
redis-cli
auth ck Qzsd43561
keys *

在浏览器输入本服务器的IP:8080(如:192.168.1.36:8080)查看是否可以看到tomcat的页面信息:

若你查看到Tomcat的主页显示:

"HTTP状态404-未找到

类型 状态报告

描述 资源服务器未能找到目标资源的表示或者不愿意公开一个已经存在的资源表示"如下图所示:

**此时面对这个404报错信息,**你需要重点检查一下你【在tomcat的conf配置文件夹下新建【redisson.json】文件(/usr/local/tomcat9/apache-tomcat-9.0.109/conf/redisson.json)】配置的Redis的地址端口是否正确、用户密码是否正确;若Redis与Tomcat不在同一台服务器上,还需要检查Redis的端口是否放开,外部服务器是否可以访问。正常状态的Tomcat主页如下图所示:

测试Tomcat结合Session的效果(在浏览器输入本服务器的IP:8080(如:192.168.1.36:8080/testsession.jsp)查看是否可以看到正常的信息显示页面)。接着在本服务器上查看redis里面是否正确记录了测试界面显示的seesionid数据。如下图所示:

到这里恭喜你表示我们安装配置的Tomcat+redisson+Redis结合成功了。

192.168.1.37服务器上安装Tomcat的部署流程与上面192.168.1.36的一致【也可以不用在该服务器上从头配置tomcat内容,只需要将192.168.1.36上的【/usr/local/tomcat9】压缩后传输给192.168.1.37服务器】后,唯一的区别就是testsession.jsp不同,及其在安装一下JDK1.8环境,如下所示:

bash 复制代码
#1-在已经完成的192.168.1.36服务器上将/usr/local/tomcat9创建为压缩包
tar -zcvf /usr/local/tomcat9.tar.gz tomcat9

#2-将创建好的tomcat.tar.gz压缩包发送到192.168.1.37的/usr/local/目录下
scp /usr/local/tomcat9.tar.gz root@192.168.1.37:/usr/local/

在192.168.1.37服务器上将testsession.jsp的内容修改为如下内容:

bash 复制代码
<%@ 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>

2.2.5、设置Tomcat开机自启

systemd服务脚本详解与管理命令_systemd service脚本-CSDN博客https://coffeemilk.blog.csdn.net/article/details/149216896

bash 复制代码
#我们这里设置Tomcat服务使用tomcat用户管理开机自启操作流程

#1-创建tomcat用户并查看
id tomcat
useradd tomcat
id tomcat

#2-进入到tomcat所在路径的父路径
cd /usr/local/

#3-将tomcat所属目录的整个内容【/usr/local/tomcat9】的属主、属组权限都修改为tomcat用户
chown -R tomcat:tomcat tomcat9


#4-编辑并创建用户下的tomcat服务实现开机自启
vi /lib/systemd/system/tomcat.service

[Unit]
Description=Apache Tomcat Web 9.0.109
After=syslog.target network.target

[Service]
Type=forking
ExecStart=/usr/local/tomcat9/apache-tomcat-9.0.109/bin/startup.sh
ExecStop=/usr/local/tomcat9/apache-tomcat-9.0.109/bin/shutdown.sh
User=tomcat
Group=tomcat
RestartSec=10
Restart=always
TimeoutStartSec=5

[Install]
WantedBy=multi-user.target


#5-重载所有服务
systemctl daemon-reload

#6-启动tomcat服务
systemctl start tomcat

#7-查看tomcat服务状态
systemctl status tomcat

#8-设置tomcat服务开机自启
systemctl enable tomcat

#9-停止tomcat服务
systemctl stop tomcat

#10-可以重启系统后查看tomcat服务状态来确定是否自启动

2.3、安装部署Nginx和配置负载均衡

接下来就是在【192.168.1.9】服务器上安装部署Nginx和配置负载均衡

使用源码安装配置Linux上的Web服务器------Nginxhttps://blog.csdn.net/xiaochenXIHUA/article/details/150780215?spm=1001.2014.3001.5501

bash 复制代码
#配置负载均衡的方法(需要在nginx的nginx.conf文件进行修改)

#1-查找我们的nginx在那个目录
whereis nginx

#2-根据查询的结果去到nginx的目录(一般使用源码安装的默认路径是【/usr/local/nginx】,此时我们可以进入sbin直接使用nginx二进制程序查看编译信息,即可确认对应的所有配置信息内容)【默认配置文件路径是:/usr/local/nginx/conf/nginx.conf】
cd /usr/local/nginx/
cd sbin
./nginx -V



#2.1-若是直接使用【yum install nginx】安装的nginx内容,则查看nginx的所有编译配置内容命令为【默认配置文件路径是:/etc/nginx/nginx.conf】
nginx -V


#3-编辑nginx.conf这个配置文件(源码安装的配置文件是/usr/local/nginx/conf/nginx.conf)
vi /usr/local/nginx/conf/nginx.conf

#3.1-编辑nginx.conf这个配置文件(yum安装的配置文件是/etc/nginx/nginx.conf)
vi /etc/nginx/nginx.conf


$4-编辑nginx.conf配置负载均衡内容:(在http模块内且在server前添加【upstream tomcat】内容、在location / 添加反向代理)【编辑好后保存退出】
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    upstream tomcat {
        server 192.168.1.36:8080 weight=1;
        server 192.168.1.37:8080 weight=1;
    }

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
                proxy_pass http://tomcat;
        }

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }
}


#5-查询到目前运行的nginx进程的父进程PID编号(如:31452)并在不影响业务的情况下重启Nginx父进程实现配置刷新
nginx -t
ps -ef | grep nginx
kill -HUP 31452

三、测试nginx+tomcat+redis的session共享功能

直接在浏览器上输入Nginx所在服务器的IP地址(如:192.168.1.9);然后在Nginx所在服务器的IP后添加/testsession.jsp后不断地刷新即可看到不断地显示tomcat2、tomcat1切换表示负载均衡生效,且该界面显示的sessionId都是一样的不会改变,则达到了我们session共享的目的,如下图所示:

相关推荐
trayvontang18 小时前
Nginx之location配置
运维·nginx
代码or搬砖20 小时前
Nginx详讲
运维·nginx·dubbo
嘻哈baby21 小时前
Redis高可用部署与集群管理实战
数据库·redis·bootstrap
Java爱好狂.1 天前
Java面试Redis核心知识点整理!
java·数据库·redis·分布式锁·java面试·后端开发·java八股文
阿杆1 天前
如何在 Spring Boot 中接入 Amazon ElastiCache
java·数据库·redis
Evan芙1 天前
Nginx 平滑升级
数据库·nginx·ubuntu
此生只爱蛋1 天前
【Redis】String 字符串
java·数据库·redis
青云交1 天前
Java 大视界 -- 基于 Java+Flink 构建实时电商交易风控系统实战(436)
java·redis·flink·规则引擎·drools·实时风控·电商交易
破烂pan1 天前
Python 整合 Redis 哨兵(Sentinel)与集群(Cluster)实战指南
redis·python·sentinel
SoleMotive.1 天前
redis和mysql有什么区别,以及redis和mysql都有什么缺点,以及什么地方redis不如mysql?
数据库·redis·mysql