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

谁说我不能喝 提交于 2020-03-13 05:14:43

一,redis介绍

redis是一个key-value存储系统。和memcached类似,它支持存储的value类型相对更多,包括string(字符串),list(列表),set(集合),zset(sorted set---有序集合)和hash(哈希类型)。与memcached一样,为了保证效率,数据都是缓存在内存中。区别是redis会周期性地把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现master-slave(主从)同步。

Redis是一个高性能的key-value数据库。redis的出现,很大程度补偿了memcacehd这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了java,C/C++,C#,php,javaScript,Perl,Object-C,python,Ruby等客户端,使用很方便。
如果简单的比较redis与memcached的区别,基本上有以下3点:
1,redis不仅仅支持简单的key/value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
2,redis支持数据的备份,即master-slave模式的数据备份。
3,redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

在Reids中,并不是所有的数据都一直存储在内存中。这是和memcacehd相比一个最大的区别。
Redis只会缓存所有的key的信息,如果Reids发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计算出那些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得redis可以保存超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的eky,因为这些数据是不会进行swap操作的。
当从Redis中读取数据的时候,如果读取的key对应的value不再内存中,那么Redis就需要从swap文件中加载相应的数据,然后再返回给请求方。

memcached和redis的比较
1,网络IO模型
memcacehd是多线程,非阻塞IO复用的网络模型,分为监听主线程和worker子线程,监听线程监听网络连接,接受请求后,将连接描述字pipe 传递给worker线程,进行读写IO,网络层使用libevent封装的事件库,多线程模型可以发挥多核作用。
Redis使用单线程的IO复用模型,自己封装了一个简单的AeEvent事件处理框架,主要实现了epoll,kqueue和select,对于单纯只有IO操作来说,单线程可以将速度优势发挥到最大,但是Redis也提供了一些简单的计算功能,比如排序,聚合等,对于这些操作,单线程模型实际会严重影响整体吞吐量,CPU计算过程中,整个IO调度都是被阻塞住的。

2,内存管理方面
memcacehd使用预分配的内存池的方式,使用slab和大小不同的chunk来管理内存,value根据大小选择合适的chunk存储。
Redis使用现场申请内存的方式来存储数据。

3,存储方式及其他方面
memcached基本只支持简单的key-value存储,不支持持久化和复制等功能,Redis除key/value之外,还支持list,set,sortedset,hash等众多数据结构。

二,如何保持session会话

目前,为了使web能适应大规模的访问,需要实现应用的集群部署。集群最有效的方案就是负载均衡,而实现负载均衡,用户每一个请求都有可能被分配到不固定的服务器上,这样我们首先要解决session的统一来保证无论用户的请求被转发到哪个服务器上都能保证用户的正常使用,即需要实现session的共享机制。

在集群系统下实现session统一的有如下几种方案:
1,请求精确定位(sessionsticky)
例如基于访问ip的hash策略,即当前用户的请求都集中定义到一台服务器中,这样单台服务器保存了用户的session登录信息,如果宕机,则等同于单点部署,会丢失,会话不复制。 (不采用)
2,session复制共享(sessionreplication):
如tomcat自带session共享,主要是指集群环境下,多台应用服务器之间同步session,使session保持一致,对外透明。如果其中一台服务器发生故障,根据负载均衡的原理,调度器会遍历寻找可用节点,分发请求,由于session已同步,故能保证用户的session信息不会丢失,会话复制。
此方案的不足之处:
必须在同一种中间件之间完成(如:tomcat-tomcat之间)
session复制带来的性能损失会快速增加,特别是当session中保存了较大的对象,而且对象变化较快时,性能下降更加显著,会消耗系统性能。这种特性使得web应用的水平扩展受到了限制。
session内容通过广播同步给成员,会造成网络流量瓶颈,即便是内网瓶颈。在大并发下表现并不好。
3,基于cache DB缓存的session共享
基于memcache/redis缓存的session共享,即使用cacheDB存储session信息,应用服务器接受新请求将session信息保存在cache DB中,当应用服务器发生故障时,调度器会遍历寻找可用节点,分发请求,当应用服务器发现session不在本机内存时,则去cache DB中查找,如果找到则复制到本机,这样实现了session共享和高可用。(推荐使用)

三,nginx+tomcat+redis+mysql实现session共享,负载均衡

1,项目环境

主机 操作系统 ip地址
nginx CentOS 7.3 172.16.1.100
tomcat-1 CentOS 7.3 172.16.1.110
tomcat-2 CentOS 7.3 172.16.1.120
mysql CentOS 7.3 172.16.1.130
Redis CentOS 7.3 172.16.1.30

2,项目拓扑

redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
在这个图中,nginx做反向代理,实现动静分离,将客户动态请求根据权重随机分配给两台tomcat服务器,redis作为两台tomcat的共享session数据服务器,mysql作为两台tomcat的后端数据库。

3,项目实施

1,nginx安装配置
使用nginx作为tomcat的负载平衡器,tomcat的会话session数据存储在redis,能够实现零宕机的7x24效果。因为将会话存储在redis中,因此nginx就不必配置称stick粘贴某个tomcat方式,这样才能真正实现后台多个tomcat负载平衡。

1)安装依赖工具包:
[root@nginx ~]#  yum -y install gcc* pcre-devel openssl-devel zlib-devel make vim 
2)创建nginx程序用户组和用户:
[root@nginx ~]# groupadd -r nginx && useradd -r -g nginx -s /bin/false -M nginx
3)编译安装nginx:
[root@nginx ~]# tar zxf nginx-1.8.0.tar.gz 
[root@nginx ~]# cd nginx-1.8.0
[root@nginx nginx-1.8.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx \
>  --with-http_stub_status_module --with-http_ssl_module  --with-http_dav_module  --with-http_flv_module \
>  --with-http_mp4_module --with-http_gzip_static_module --with-http_gzip_static_module \
> --with-http_addition_module --with-http_sub_module  --with-pcre  --with-http_realip_module 
[root@nginx nginx-1.8.0]# make && make install
4)优化路径并检查:
[root@nginx nginx-1.8.0]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
[root@nginx nginx-1.8.0]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
5)编写nginx服务脚本:
[root@nginx nginx-1.8.0]# vim /etc/init.d/nginx
#!/bin/bash
# chkconfig: 2345 99 20
# description: Nginx Service Control Script
PROG="/usr/local/nginx/sbin/nginx"
PIDF="/usr/local/nginx/logs/nginx.pid"
case "$1" in
start)
netstat -anplt |grep ":80" &> /dev/null && pgrep "nginx" &> /dev/null
if [ $? -eq 0 ]
then
echo "Nginx service already running."
else
$PROG -t &> /dev/null
if [ $? -eq 0 ] ; then
$PROG
echo "Nginx service start success."
else
$PROG -t
fi
fi
;;
stop)
netstat -anplt |grep ":80" &> /dev/null && pgrep "nginx" &> /dev/null
if [ $? -eq 0 ]
then
kill -s QUIT $(cat $PIDF)
echo "Nginx service stop success."
else
echo "Nginx service already stop"
fi
;;
restart)
$0 stop
$0 start
;;
status)
netstat -anplt |grep ":80" &> /dev/null && pgrep "nginx" &> /dev/null
if [ $? -eq 0 ]
then
echo "Nginx service is running."
else
echo "Nginx is stop."
fi
;;
reload)
netstat -anplt |grep ":80" &> /dev/null && pgrep "nginx" &> /dev/null
if [ $? -eq 0 ]
then
$PROG -t &> /dev/null
if [ $? -eq 0 ] ; then
kill -s HUP $(cat $PIDF)
echo "reload Nginx config success."
else
$PROG -t
fi
else
echo "Nginx service is not run."
fi
;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
esac
#并加入开机自启:
[root@nginx ~]# chkconfig --add nginx
[root@nginx ~]# chkconfig nginx on
#启动nginx:
[root@nginx ~]# systemctl daemon-reload
[root@nginx ~]# systemctl start nginx
[root@nginx ~]# netstat -anput | grep nginx
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      21812/nginx: master 

6)配置nginx反向代理(反向代理+负载均衡+健康检测)
注:结合proxy和upstream模块实现后端web负载均衡;
结合nginx默认自带的ngx_http_proxy_module模块 和ngx_http_upstream_module模块实现后端服务器的健康检查;

[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
在http{}字段中添加以下配置项:

#load balance Settings:
        upstream  backend_tomcat {   
                server 172.16.1.110:8080 weight=1 max_fails=2 fail_timeout=10s;
                server 172.16.1.120:8080 weight=1 max_fails=2 fail_timeout=10s;
}
# http_proxy Settings:
        proxy_connect_timeout 75;   #nginx 跟后端服务器连接超时时间(代理连接超时)
        proxy_send_timeout 75;   #定义后端服务器的数据回传时间,即在规定时间之内后端服务器必须传完所有的数据,否则,nginx将断开这个连接。
        proxy_read_timeout 75;  #定义从后端服务器读取响应的超时
        proxy_buffer_size 4k;  #设置缓冲区的大小(该缓冲区大小默认等于 proxy_buffers 指令设置的一块缓冲区的大小,但它也可以被设置得更小)
        proxy_buffers 4 32k;    #为每个连接设置缓冲区的数量和每块缓冲区的大小
        proxy_busy_buffers_size 64k;  #高负荷下缓冲大小(默认大小是 proxy_buffers 指令设置单块缓冲大小的 2 倍)
        proxy_temp_file_write_size 64k;  #当缓存被代理的服务器响应到临时文件时,这个选项限制每次写临时文件的大小
参数解释:
weight:轮询权值,也是可以用在ip_hash的,默认值为1
max_fails:运行请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream模块定义的错误。
fail_timeout:有两层含义,以时在10s时间内最多容许2次失败;二是在经历了2次失败以后,10s时间内不分配请求到这台服务器。

在server模块中添加:

#proxy_pass Settings:
        location ~* \.(jsp|do)$ {   #匹配到的动态请求将进行转发
        proxy_pass http://backend_tomcat;  #请求转向 backend 定义的服务器列表,即反向代理,对应 upstream 负载均衡器。
        proxy_redirect off;  #是否定义重定向规则
        proxy_set_header Host $host;  #允许重新定义或者添加发往后端服务器的请求头
        proxy_set_header X-Real-IP $remote_addr;   #web服务器端获得用户的真实ip, 也可以通过下面的X-Forward-For获取
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;    #后端的 Web 服务器可以通过 X-Forwarded-For 获取用户真实 IP
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
#增加故障转移,如果后端的服务器返回502、 504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移
}

7)重启nginx服务并设置防火墙规则:

[root@nginx ~]# systemctl restart nginx
[root@nginx ~]# firewall-cmd --add-port=80/tcp --permanent
success
[root@nginx ~]# firewall-cmd --reload
success

2,安装部署tomcat服务器
在安装tomcat之前必须先安装JDK,JDK是sun公司免费提供的java语言的软件开发工具包,其中包含java虚拟机(JVM),编写好的java源程序经过编译可形成java字节码,只要安装了JDK,就可以利用JVM解释这些字节码文件,从而保证了java的平台性。

1)安装JDK,配置java环境(tomcat1和tomcat2 服务器安装)

[root@tomcat-1 ~]# tar zxf jdk-8u211-linux-x64.tar.gz
[root@tomcat-1 ~]# mv jdk1.8.0_211/ /usr/local/java
[root@tomcat-1 ~]# vim /etc/profile
export JAVA_HOME=/usr/local/java
export PATH=$JAVA_HOME/bin:$PATH
[root@tomcat-1 ~]# source /etc/profile
[root@tomcat-1 ~]# java -version  #确保java版本与当前版本一致
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)

2)安装tomcat(tomcat1和tomcat2 服务器相同操作)
可在tomcat官网中下载需要的版本:https://tomcat.apache.org

[root@tomcat-1 ~]# tar zxf apache-tomcat-8.5.35.tar.gz 
[root@tomcat-1 ~]# mv apache-tomcat-8.5.35 /usr/local/tomcat8
[root@tomcat-1 ~]# vim /etc/profile
export CATALINA_HOME=/usr/local/tomcat8
export PATH=$JAVA_HOME/bin:$CATALINA_HOME/bin:$PATH
[root@tomcat-1 ~]# source /etc/profile
#启动tomcat:
[root@tomcat-1 ~]# /usr/local/tomcat8/bin/startup.sh   
#这里只是展示启动脚本的路径,因为上边设置了环境变量,可直接执行startup.sh脚本
Using CATALINA_BASE:   /usr/local/tomcat8
Using CATALINA_HOME:   /usr/local/tomcat8
Using CATALINA_TMPDIR: /usr/local/tomcat8/temp
Using JRE_HOME:        /usr/local/java
Using CLASSPATH:       /usr/local/tomcat8/bin/bootstrap.jar:/usr/local/tomcat8/bin/tomcat-juli.jar
Tomcat started.
[root@tomcat-1 ~]# netstat -anput | grep 8080
tcp6       0      0 :::8080                 :::*                    LISTEN      15408/java
#防火墙规则配置:
[root@tomcat-1 ~]# firewall-cmd --add-port=8080/tcp --permanent
success
[root@tomcat-1 ~]# firewall-cmd --reload
success

#浏览器测试访问两台tomcat服务器
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)

3)修改tomcat配置文件(tomcat1和tomcat2操作)

[root@tomcat-1 ~]# vim /usr/local/tomcat8/conf/server.xml
#设置默认虚拟主机,并增加jvmRoute
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat-1">
#修改默认虚拟主机,并将网站文件路径指向/web/webapp1,在host段增加context段
 <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
                <Context docBase="/web/webapp1" path="" reloadable="true"/>   #添加该行内容

#tomcat-2服务器的配置文件:

#两台配置只是jvmRoute不同,其他配置保持一致:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat-2">
<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
                  <Context docBase="/web/webapp1" path="" reloadable="true"/> 

说明:jvmRoute是jvm标识,就是页面最顶部的标签,在实际生产环境中,所有的后台tomcat标识都要一样,这里为了实验的说明性,我两台tomcat的标识改成不一样的。等会为了验证时候好验证。

4)创建网页目录与测试文件:(tomcat-1和tomcat-2操作相同)

[root@tomcat-1 ~]# mkdir -p /web/webapp1
[root@tomcat-1 ~]# vim /web/webapp1/index.jsp  #编写动态网页文件
#内容如下:
<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>tomcat-1</title>   
</head>
<body>
<h1><font color="red">Session serviced by tomcat</font></h1>
<table aligh="center" border="1">
<tr>
<td>Session ID</td>
<td><%=session.getId() %></td>
<% session.setAttribute("abc","abc");%>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
<html>

#注意:为了测试负载均衡,tomcat-2节点index.jsp文件的title修改为“tomcat-2”(生产环境两个tomcat服务器提供的网页内容是相同的),其他配置相同。

5)重启tomct服务,并验证负载均衡

#tomcat-1和tomcat-2都需要重启
[root@tomcat-1 ~]# shutdown.sh 
[root@tomcat-1 ~]# startup.sh   
[root@tomcat-1 ~]# netstat -anput | grep 8080
tcp6       0      0 :::8080                 :::*                    LISTEN      15551/java  

#用户使用浏览器通过访问nginx web服务,验证负载均衡:
第一次访问的结果:
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
第二次访问的结果:
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
从上面的结果能看出两次访问,nginx把访问请求分别分发给了后端的tomcat-1和tomcat-2,客户端的访问请求实现了负载均衡,但session id不一样(即:没有实现session保持),这样的话,会给后端服务器造成很大的压力。

6)验证健康检查

#可以关掉一台tomcat主机,模拟宕机,用客户端浏览器测试访问
[root@tomcat-1 ~]# shutdown.sh   
Using CATALINA_BASE:   /usr/local/tomcat8
Using CATALINA_HOME:   /usr/local/tomcat8
Using CATALINA_TMPDIR: /usr/local/tomcat8/temp
Using JRE_HOME:        /usr/local/java
Using CLASSPATH:       /usr/local/tomcat8/bin/bootstrap.jar:/usr/local/tomcat8/bin/tomcat-juli.jar

redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
无论你怎么刷新页面,一直都是tomcat2提供服务,说明健康检查起到了作用,验证成功。

3,配置tomcat通过redis实现会话保持

#前边可以说是准备工作,下面才是该项目的重点。
1)安装redis
官网下载地址:http://download.redis.io/releases/
[root@redis ~]# tar zxf redis-4.0.14.tar.gz
[root@redis ~]# cd redis-4.0.14/
[root@redis redis-4.0.14]# make && make install
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
通过上图,我们可以很容易的看出,redis安装到/usr/local,/usr/local/bin,/usr/local/share,/usr/local/include,/usr/local/lib,/usr/local/share/man目录下。

#然后再切换到utils目录下,执行redis初始化脚本install_server.sh,如下:

[root@redis redis-4.0.14]# cd utils/
[root@redis utils]# ./install_server.sh 
Welcome to the redis service installer
This script will help you easily set up a running redis server

Please select the redis port for this instance: [6379] 
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf] 
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log] 
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379] 
Selected default - /var/lib/redis/6379
Please select the redis executable path [/usr/local/bin/redis-server] 
Selected config: 
Port           : 6379  
Config file    : /etc/redis/6379.conf  
Log file       : /var/log/redis_6379.log
Data dir       : /var/lib/redis/6379
Executable     : /usr/local/bin/redis-server  
Cli Executable : /usr/local/bin/redis-cli
Is this ok? Then press ENTER to go on or Ctrl-C to abort.
Copied /tmp/6379.conf => /etc/init.d/redis_6379
Installing service...
Successfully added to chkconfig!
Successfully added to runlevels 345!
Starting Redis server...
Installation successful!
#上面全部默认回车就好

通过上面的安装过程,我们可以看出redis初始化后redis配置文件为/etc/redis/6379.conf,日志文件为/var/log/redis_6379.log,数据文件dump.rdb存放到/var/lib/redis/6379目录下,启动脚本为/etc/init.d/redis_6379。
#如果需要使用systemd,可以在/etc/systemd/system 下创建一个单位文件名字为redis_6379.service。

[root@redis utils]# vim /etc/systemd/system/redis_6379.service
#内容如下:
[Unit]
Description=Redis on port 6379
[Service]
Type=forking
ExecStart=/etc/init.d/redis_6379 start
ExecStop=/etc/init.d/redis_6379 stop
[Install]
WantedBy=multi-user.target
#注:这里Type=forking是后台运行的形式

#启动redis
[root@redis utils]# systemctl daemon-reload
[root@redis utils]# systemctl enable redis_6379.service
[root@redis utils]# systemctl start redis_6379.service
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
#从上图我们可以看到,服务状态是死亡状态,解决办法就是重启一下服务即可,如下图所示:
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)

#防火墙规则设置:
[root@redis utils]# firewall-cmd --add-port=6379/tcp --permanent
success
[root@redis utils]# firewall-cmd --reload
success

2)配置redis

[root@redis ~]# vim /etc/redis/6379.conf 
#修改内容如下(去掉注释并修改):
bind 172.16.1.30   #将redis的监听地址修改为redis主机的ip
requirepass pwd@123   #考虑到安全性,需要启动redis的密码验证功能requirepass参数。
#重新启动redis服务:
[root@redis ~]# systemctl restart redis_6379.service
[root@redis ~]# netstat -anput | grep redis
tcp        0      0 172.16.1.30:6379        0.0.0.0:*               LISTEN      12261/redis-server 

#redis配置文件配置完毕后,启动redis并进行简单操作(测试),如下:

[root@redis ~]# redis-cli -h 172.16.1.30 -p 6379 -a pwd@123
Warning: Using a password with '-a' option on the command line interface may not be safe.
172.16.1.30:6379> keys *
(empty list or set)
172.16.1.30:6379> set name lisi
OK
172.16.1.30:6379> get name
"lisi"
172.16.1.30:6379> quit   

以上参数解释:

首先我们利用redis的命令行工具redis-cli,连接redis服务器,ip是172.16.1.30(这里就以本机进行测试),端口是6379,密码是pwd@123
keys *:是查看redis所有的键值对
set nam lisi:添加一个key(name)-value(lisi)
get name:查看name这个键值的内容
quit:退出连接
#redis的其他操作命令,会在后面讲解到

到此,redis的所有部署完毕,接下来配置tomcat的session同步。

3)配置tomcat session redis同步(tomcat1和tomcat2操作相同)
#下载tomcat-redis-session-manager相应的jar包,主要有三个:

tomcat85-session-redis-1.0.jar
jedis-2.9.0.jar
commons-pool2-2.4.2.jar
① 下载完成后分别拷贝到$TOMCAT_HOME/lib目录中:
[root@tomcat-1 ~]# cp tomcat85-session-redis-1.0.jar jedis-2.9.0.jar commons-pool2-2.4.2.jar  /usr/local/tomcat8/lib/
② 修改tomcat的context.xml文件:
[root@tomcat-1 ~]# vim /usr/local/tomcat8/conf/context.xml 
添加以下内容:

redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
图中内容如下:

        <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
        <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
        host="172.16.1.30"   #redis主机地址
        password="pwd@123"   #redis登录密码
        port="6379"        #监听端口
        database="0"   
        maxInactiveInterval="60" />    #session的失效时间(单位s)
③ 修改完,重启tomcat:
[root@tomcat-1 ~]# shutdown.sh 
[root@tomcat-1 ~]# startup.sh 
[root@tomcat-1 ~]# netstat -anput | grep 8080
tcp6       0      0 :::8080                 :::*                    LISTEN      16931/java  

在tomcat-2主机上重复以上操作。

④验证session会话是否一致
#模拟用户通过浏览器访问http://172.16.1.100/index.jsp 测试页
第一次访问:
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)

第二次访问(刷新页面):
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
可以看出,分别访问了不同的tomcat,但是得到的session却是相同的,说明session会话保持同步,达到了集群的目的。
注:从tomcat6开始默认开启了session持久化设置,测试时可以关闭本地session持久化,其实也很简单,在tomcat的conf目录下的context.xml文件中,取消注释下面那段配置即可:

#修改前:
    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->
#修改后:
    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <Manager pathname="" />
⑤ 查看redis:
[root@redis ~]# redis-cli -h 172.16.1.30 -p 6379 -a pwd@123
Warning: Using a password with '-a' option on the command line interface may not be safe.
172.16.1.30:6379> keys *
1) "3585F7426EBBC83802C0407575FEAC72tMLrlI.tomcat-2"
2) "name"
172.16.1.30:6379> quit

可以看出,redis为保持在tomcat2上的session会话保持建立了键值对。

4, 配置tomcat连接数据库

tomcat的session会话保持通过redis把这个问题解决掉了,现在该解决tomcat连接数据库问题了。(主机172.16.1.130作为mysql DB 服务器)
1)安装mysql服务(二进制方式)

[root@mysql ~]# vim mysql5.7.sh
#!/bin/bash
rpm -qa | grep mariadb  &> /dev/null
if [ $? -eq 0 ]
then
    rpm -e mariadb-libs --nodeps
fi
tar zxf  mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz 
mv mysql-5.7.28-linux-glibc2.12-x86_64 /usr/local/mysql
ln -s /usr/local/mysql/bin/* /usr/local/bin
groupadd -r mysql && useradd -r -g mysql -s /bin/false -M mysql
mkdir /usr/local/mysql/data
chown -R mysql:mysql /usr/local/mysql
cat > /etc/my.cnf <<EOF
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
pid-file=/usr/local/mysql/data/mysqld.pid
log-error=/usr/local/mysql/data/mysql.err
socket=/tmp/mysql.sock
[client]
socket=/tmp/mysql.sock
EOF
mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
chown -R mysql:mysql /usr/local/mysql
cd /usr/local/mysql/
cp support-files/mysql.server /etc/init.d/mysqld
chmod +x /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on
service mysqld start
mypwd=`grep password /usr/local/mysql/data/mysql.err | awk -F'root@localhost: ' '{print $2}'`
mysql -uroot -p${mypwd} -e 'alter user root@localhost identified by"123.com"' --connect-expired-password
[root@mysql ~]# sh mysql5.7.sh 
Starting MySQL. SUCCESS! 
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@mysql ~]# ss -anput | grep 3306
tcp    LISTEN     0      80       :::3306                 :::*                   users:(("mysqld",pid=16753,fd=12))
#防火墙规则设置:
[root@mysql ~]# firewall-cmd --add-port=3306/tcp --permanent
success
[root@mysql ~]# firewall-cmd --reload
success

2)在数据库中创建数据

[root@mysql ~]# mysql -uroot -p123.com
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> grant all on *.* to javauser@'172.16.1.%' identified by 'pwd@123';   //授权一个用户
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> flush privileges;   
Query OK, 0 rows affected (0.00 sec)

mysql> create database javadb;   //创建库
Query OK, 1 row affected (0.00 sec)

mysql> use javadb
Database changed
mysql> create table testtb(id int primary key auto_increment,
    -> name varchar(25),
    -> age int(3));   //创建表
Query OK, 0 rows affected (0.00 sec)

mysql> insert into testtb(name,age) values('zhangsan','20'),('lisi','21'),('sunqian','22');   //插入数据
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from testtb;  #查看一下
+----+----------+------+
| id | name     | age  |
+----+----------+------+
|  1 | zhangsan |   20 |
|  2 | lisi     |   21 |
|  3 | sunqian  |   22 |
+----+----------+------+
3 rows in set (0.00 sec)

3)配置tomcat服务器连接mysql数据库(两台tomcat操作相同)

(1)下载mysql-connector-java-5.1.22-bin.jar并复制到$CATALINA_HOME/lib目录下:
[root@tomcat-1 ~]# cp mysql-connector-java-5.1.22.jar  /usr/local/tomcat8/lib/
(2)Context文件设置:
[root@tomcat-1 ~]# vim /usr/local/tomcat8/conf/context.xml

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

#上图在<Context>中添加的内容如下:
        <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
        maxActive="100" maxIdle="30" maxWait="10000"
        username="javauser" password="pwd@123" driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://172.16.1.130:3306/javadb"/>

(3)在/web/webapp1/根目录下新建目录,用于存放网站xml配置文件,用于tomcat连接mysql数据库

[root@tomcat-1 ~]# mkdir /web/webapp1/WEB-INF
[root@tomcat-1 ~]# vim /web/webapp1/WEB-INF/web.xml
添加内容如下:
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<description>MySQL Test App</description>
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/TestDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
#保存修改并退出,重启tomcat服务:
[root@tomcat-1 ~]# shutdown.sh 
Using CATALINA_BASE:   /usr/local/tomcat8
Using CATALINA_HOME:   /usr/local/tomcat8
Using CATALINA_TMPDIR: /usr/local/tomcat8/temp
Using JRE_HOME:        /usr/local/java
Using CLASSPATH:       /usr/local/tomcat8/bin/bootstrap.jar:/usr/local/tomcat8/bin/tomcat-juli.jar
[root@tomcat-1 ~]# startup.sh 
Using CATALINA_BASE:   /usr/local/tomcat8
Using CATALINA_HOME:   /usr/local/tomcat8
Using CATALINA_TMPDIR: /usr/local/tomcat8/temp
Using JRE_HOME:        /usr/local/java
Using CLASSPATH:       /usr/local/tomcat8/bin/bootstrap.jar:/usr/local/tomcat8/bin/tomcat-juli.jar
Tomcat started.

tomcat-2进行和tomcat-1相同的操作。
(4)测试代码
#现在创建一个简单的测试.jsp页面,测试tomcat和mysql的连通性

[root@tomcat-1 ~]# vim /web/webapp1/test.jsp
#内容如下:(根据自己的环境,修改相对应的参数)
<%@ page language="java" import="java.sql.*" pageEncoding="GB2312"%>
<html>
<head>
<title>MySQL</title>
</head>
<body>
connect MySQL<br>
<%
String driverClass="com.mysql.jdbc.Driver";
String url="jdbc:mysql://172.16.1.130:3306/javadb";
String username = "javauser";
String password = "pwd@123";
Class.forName(driverClass);
Connection conn=DriverManager.getConnection(url, username, password);
Statement stmt=conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from testtb");
while(rs.next()){
out.println("<br>name:"+rs.getString(2)+"age:"+rs.getString(3));
}
rs.close();
stmt.close();
conn.close();
%>
</body>
</html>

注:在tomcat-2节点上创建同样的测试代码,但是为了更好的验证,把标题修改为”MySQL-2“。

(5)通过浏览器进行访问测试页,URL:http://172.16.1.100/test.jsp ,还是通过nginx反向代理后端的tomcat服务器。
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)
从上图可以看出,现在tomcat-1和tomcat-2已经可以连接到数据库了。
到此,项目搭建完毕。。。

安装包和jar包已上传至网盘:链接:https://pan.baidu.com/s/133H7oEbBWiBvaNWUoFgH3Q
提取码:2fj1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!