龙空技术网

十分钟掌握Tomcat集群Session共享方法

删库跑路吧 3917

前言:

目前兄弟们对“nginxtomcat会话保持”大致比较珍视,我们都需要了解一些“nginxtomcat会话保持”的相关内容。那么小编在网络上汇集了一些对于“nginxtomcat会话保持””的相关文章,希望姐妹们能喜欢,小伙伴们一起来了解一下吧!

技能目标:

· 了解Session共享解决方案

· 掌握Tomcat集群Session共享方法

8.1案例分析

8.1.1案例概述

HTTP协议属于无状态协议,当完成数据交换时,客户端与服务器端的连接就会关闭;但再次进行数据交换时,就需要建立新的连接。这意味着服务器无法从连接上跟踪会话,客户端与服务器端之间的联系是离散的、非连续性的。当用户在同一网站的多个页面转换时,服务器无法确定是否是同一用户。例如:用户登录淘宝后进入商品页购买商品,但是服务器不能将用户和商品对应起来。因此,需要通过Session会话跟踪技术来实现追踪定位,以保证用户在多次切换时,服务器可以保存该用户的相关信息,使用Session技术可以实现会话跟踪。

8.1.2案例前置知识点

1. Session概述

Session(中文为"会话")在计算机中被称之为"会话控制",是指一个终端用户与交互系统进行通信的时间间隔,通常是指从登录进入系统开始到注销退出系统结束之间的所用时间。Session所包括的客户端、服务器端以及不中断的操作时间,决定Session的不同。例如:用户A和服务器C建立连接时所处的Session与用户B和服务器C建立连接时所处的Session是两个完全不同的Session。

2. Session共享方案

对于Web应用集群的技术而言,最大的难点是在集群中多个节点之间保持数据的一致性,其中会话(Session)信息是这些数据中最重要的一部分。要实现这一点, 可以采用以下两种方式。

· 把所有Session数据放到一台服务器上或者数据库中,集群中的所有节点通过访问这台Session服务器来获取数据;

· 在集群中的所有节点间进行Session数据的同步拷贝,任何一个节点均保存了所有的Session数据。

在集群中可以通过以下几种方案实现Session共享:

(1) 请求精确定位

例如基于访问IP地址的Hash策略,即当前用户的请求都集中定位到一台服务器中,这样单台服务器就会保存用户的Session登录信息。但是如果宕机,则等同于单点故障,保存用户的Session登录信息就会丢失,会话不复制。

(2) Session复制共享

例如Tomcat自带Session共享,主要是指集群环境下多台应用服务器之间同步Session,使Session保持一致,对外则是保持透明。 如果其中一台服务器发生故障,根据负载均衡的原理,调度器会遍历寻找可用节点来分发请求。由于Session已同步,所以能够保证用户的Session信息不会丢失,也就是所谓的会话复制。

但是这个方案存在以下几个缺点:

· 必须在同一种中间件之间完成,例如Tomcat与Tomcat之间;

· Session复制带来的性能损失会快速增加,特别是当Session中保存了较大的对象,而且对象变化较快时,性能下降更加显著,会大量消耗系统性能。这种特性使得Web应用的水平扩展受到了限制。

· Session内容通过广播同步给成员,会造成网络流量瓶颈。

(3) 基于高速缓存数据库的Session共享

基于Memcached/Redis缓存的Session共享,即使用高速缓存数据库存取Session信息,应用服务器接受新请求将Session信息保存在高速缓存数据库中。应用服务器发生故障时,调度器会遍历寻找可用节点来分发请求,当应用服务器发现Session不在本机内存时,则去高速缓存数据库中查找。如果找到则复制到本机,这样实现Session共享和高可用。

3.Tomcat集群Session同步方案

Tomcat集群Session同步方案有以下几种方式:

(1)使用Tomcat自带的Cluster方式

多个Tomcat之间自动实时复制Session信息,配置起来比较简单。但这个方案的效率比较低。

(2)利用Nginx的基于访问IP地址的Hash路由策略

保证访问的IP地址始终被路由到同一个Tomcat上。每个请求按访问IP地址的Hash结果分配,这样每个访客固定访问一个后端服务器,可以解决Session的问题。

(3)利用Nginx插件实现Tomcat集群和Session同步

nginx-upstream-jvm-route是一个Nginx的扩展模块,用来实现基于Cookie的Session Sticky(会话粘滞)的功能。但是这个模块的补丁在Nginx1.4版本之后就没有再更新了,所以Nginx1.4之后版本跟该模块就不兼容。

(4)利用Memcached实现(MSM工具)

Memcached存储Session,并把多个Tomcat的Session集中管理,前端利用Nginx实现负载均衡和动静态资源分离,在兼顾系统水平扩展的同时又能保证较高的性能。其原理是通过MSM工具把Tomcat的Session序列化后保存到Memcached里面,从而实现Session共享。

MSM是一个高可用的Tomcat Session共享解决方案,除了可以从本机内存快速读取Session信息(仅针对黏性Session)外,还可使用Memcached存取Session,以实现高可用。传统Tomcat集群,会话复制随着结点数增多,扩展性成为瓶颈。MSM使用memcached完成统一管理Tomcat会话,避免Tomcat节点之间过多会话复制。

MSM利用Value(Tomcat 阀)对Request进行跟踪。Request请求到来时,从Memcached加载Session,Request请求结束时将Tomcat Session更新至Memcached,以达到Session共享DE 目的,支持Sticky和Non-Sticky模式:

· Sticky :会话粘连模式(黏性Session)。客户端在一台Tomcat实例上完成登录后,以后的请求均会根据IP直接绑定到该Tomcat实例。

· Non-Sticky:会话非粘连模式(非粘性Session)。客户端的请求是随机分发,多台Tomcat实例都会收到请求。

(5)利用Redis实现

使用Redis不仅仅是因为它可以将缓存的Session持久化,还因为它支持的单个对象比较大,而且数据类型丰富。也就是说Redis不仅仅可以用于缓存 Session,还可以做其他用途。Redis这种方式目前还不支持Tomcat8环境(现在网上插件不支持Tomcat8,想要支持Tomcat8的话,则需修改插件jar包的源代码)。

在Tomcat集群中,当一个节点出现故障,虽然有高可用集群来负责故障转移,但用户的Session信息如何保持呢?下面通过案例的方式具体介绍上述所说的第4种Tomcat集群Session同步方案:使用MSM(Memcached-Session-Manager)进行Session复制同步,即利用MSM+Memcached实现Session共享。

8.1.3案例环境

1.案例环境

本案例的实验环境如表8-1所示。

表8-1 实验环境

案例实验环境的网络拓扑如图8.1所示。

图8.1 实验拓扑

2.案例需求

本案例的需求如下:

利用Nginx实现Tomcat集群的负载均衡和动静态资源分离,并结合Memcached实现Session共享。

3.案例实现思路

本案例的实现思路如下:

(1) 为主机进行基本配置;

(2) 安装配置Tomcat服务;

(3) 安装配置Nginx服务;

(4) 安装配置Memcached服务;

(5) 配置Session共享。

8.2案例实施

8.2.1主机配置

1.设置主机名

设置IP地址为192.168.9.91的主机的主机名为nginx-node,具体操作如下所示。

[root@localhost ~]# hostnamectl set-hostname nginx-node

[root@localhost ~]# bash

[root@nginx-node ~]#

设置IP地址为192.168.9.71的主机的主机名为tomcat-node1,具体操作如下所示。

[root@localhost ~]# hostnamectl set-hostname tomcat-node1

[root@localhost ~]# bash

[root@tomcat-node1 ~]#

设置IP地址为192.168.9.74的主机的主机名为tomcat-node2,具体操作如下所示。

[root@localhost ~]# hostnamectl set-hostname tomcat-node2

[root@localhost ~]# bash

[root@tomcat-node2 ~]#

设置IP地址为192.168.9.77的主机的主机名为mem-node1,具体操作如下所示。

[root@localhost ~]# hostnamectl set-hostname mem-node1

[root@localhost ~]# bash

[root@mem-node1 ~]#

设置IP地址为192.168.9.79的主机的主机名为mem-node2,具体操作如下所示。

[root@localhost ~]# hostnamectl set-hostname mem-node2

[root@localhost ~]# bash

[root@mem-node2 ~]#

2.关闭防火墙与SELinux

关闭所有主机上的Firewalld防火墙与SELinux,并重启主机使配置生效。下面以nginx-node主机为例进行操作演示。

[root@nginx-node ~]# systemctl stop firewalld

[root@nginx-node ~]# systemctl disable firewalld

Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.

Removed symlink /etc/systemd/system/basic.target.wants/firewalld.service.

[root@nginx-node ~]# sed -i '/SELINUX/s/enforcing/disabled/' /etc/selinux/config

[root@nginx-node ~]# reboot

[root@nginx-node ~]# systemctl status firewalld

● firewalld.service - firewalld - dynamic firewall daemon

Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)

Active: inactive (dead)

Docs: man:firewalld(1)

[root@nginx-node ~]# getenforce

Disabled

8.2.2安装Tomcat

1.安装Java环境

在tomcat-node1与tomcat-node2两台主机上都与需要安装Java环境,下面以tomcat-node1主机为例进行操作演示。

[root@tomcat-node1 ~]# yum install -y java

[root@tomcat-node1 ~]# java -version

openjdk version "1.8.0_191"

OpenJDK Runtime Environment (build 1.8.0_191-b12)

OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)

2.安装Tomcat

在tomcat-node1与tomcat-node2两台主机上都与需要安装Tomcat,下面以tomcat-node1主机为例进行操作演示。

[root@tomcat-node1 ~]# cd /usr/local/src/

[root@tomcat-node1 src]# ll apache-tomcat-8.5.16.tar.gz

-rw-r--r-- 1 root root 9417469 7月 27 2017 apache-tomcat-8.5.16.tar.gz

[root@tomcat-node1 src]# tar -zvxf apache-tomcat-8.5.16.tar.gz

[root@tomcat-node1 src]# mv apache-tomcat-8.5.16 /usr/local/tomcat8

[root@tomcat-node1 src]# /usr/local/tomcat8/bin/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

Using CLASSPATH: /usr/local/tomcat8/bin/bootstrap.jar:/usr/local/tomcat8/bin/tomcat-juli.jar

Tomcat started.

[root@tomcat-node1 src]# ps -ef | grep tomcat

root 2303 1 19 22:01 pts/0 00:00:05 /usr/bin/java -Djava.util.logging.config.file=/usr/local/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -classpath /usr/local/tomcat8/bin/bootstrap.jar:/usr/local/tomcat8/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat8 -Dcatalina.home=/usr/local/tomcat8 -Djava.io.tmpdir=/usr/local/tomcat8/temp org.apache.catalina.startup.Bootstrap start

root 2320 2144 0 22:01 pts/0 00:00:00 grep --color=auto tomcat

[root@tomcat-node1 src]# lsof -i:8080

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME

java 2303 root 48u IPv6 20206 0t0 TCP *:webcache (LISTEN)

3.编写测试页面

tomcat-node1主机上编写的测试页面,具体内容如下所示。

[root@tomcat-node1 ~]# cat /usr/local/tomcat8/webapps/ROOT/index.jsp

<html>

<body bgcolor="green">

<center>

<%= request.getSession().getId() %>

<h1>192.168.9.71</h1>

<h1>port:8080</h1>

<h1>this is Tomcat-node1 ! </h1>

</center>

</body>

</html>

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false"%>

SessionID:<%=session.getId()%><BR>

SessionIP:<%=request.getServerName()%> <BR>

SessionPort:<%=request.getServerPort()%>

<% out.println("This is Tomcat server 71 !"); %>

tomcat-node2主机上编写的测试页面,具体内容如下所示。

[root@Tomcat-node2 ~]# cat /usr/local/tomcat8/webapps/ROOT/index.jsp

<html>

<body bgcolor="green">

<center>

<%= request.getSession().getId() %>

<h1>192.168.9.74</h1>

<h1>port:8080</h1>

<h1>this is Tomcat-node2 ! </h1>

</center>

</body>

</html>

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false"%>

SessionID:<%=session.getId()%><BR>

SessionIP:<%=request.getServerName()%> <BR>

SessionPort:<%=request.getServerPort()%>

<% out.println("This is Tomcat server 74 !"); %>

8.2.3安装Nginx服务

在Nginx-node主机上安装配置Nginx服务,具体操作如下所示。

[root@nginx-node ~]# yum -y install zlib-devel pcre-devel openssl-devel gcc gcc-c++ //安装依赖包与编译环境

[root@nginx-node ~]# ll nginx-1.12.0.tar.gz

-rw-r--r-- 1 root root 980831 7月 11 2017 nginx-1.12.0.tar.gz

[root@nginx-node ~]# tar xf nginx-1.12.0.tar.gz

[root@nginx-node ~]# cd nginx-1.12.0

[root@nginx-node nginx-1.12.0]# ./configure && make && make install

[root@nginx-node nginx-1.12.0]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/

[root@nginx ~]# cd

[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf

//修改配置文件以实现对Tomcat负载均衡

http {

upstream backend {

server 192.168.9.71:8080 weight=1 max_fails=1 fail_timeout=10s;

server 192.168.9.74:8080 weight=1 max_fails=1 fail_timeout=10s;

}

server {

listen 80;

server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {

root html;

index index.html index.htm;

proxy_pass ;

}

}

}

events {

worker_connections 1024;

}

[root@nginx ~]# 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

[root@nginx ~]# nginx

启动Nginx服务后访问,发现访问请求结果会负载到192.168.9.71和192.168.9.74的Tomcat上,如图8.2与8.3所示。注:如果浏览器一直不切换页面,请清除浏览器缓存。

如上图8.2、图8.3所示,在配置Memcached-Session-Manager会话共享之前,访问的请求会轮询负载到tomcat-node1和tomcat-node2两个节点上,并且Session ID会随着页面的刷新而改变,即此时还没有实现Session会话共享。

8.2.4安装Memcached

Memcached是一款免费、开源、分布式的内存对象缓存系统, 主要用于减少数据库的负载, 加快Web应用程序的访问。Memcached虽然简单但是功能很强大, 其简单的设计加快了部署过程,同时也易于开发, 缓存则解决了面临的大量数据时很多的问题。依次执行以下命令安装并启动Memcached,以下操作mem-node1与mem-node2主机上都需要执行。

[root@mem-node1 ~]# yum -y install libevent libevent-devel gcc gcc-c++ lsof

[root@mem-node1 ~]# cd /usr/local/src/

[root@mem-node1 src]# ll memcached-1.4.34.tar.gz

-rw-r--r-- 1 root root 391131 6月 27 07:41 memcached-1.4.34.tar.gz

[root@mem-node1 src]# tar -zxf memcached-1.4.34.tar.gz

[root@mem-node1 src]# cd memcached-1.4.34

[root@mem-node1 memcached-1.4.34]# ./configure --prefix=/usr/local/memcached

[root@mem-node1 memcached-1.4.34]# make && make install

[root@mem-node1 memcached-1.4.34]# cd

[root@mem-node1 ~]# /usr/local/memcached/bin/memcached -d -m 512 -u root -p 11211 -c 1024 -P /var/lib/memcached.11211pid

//启动Memcached,端口11211可以根据自己需要修改不同端口

[root@mem-node1 ~]# ps -ef | grep memcached //查看Memcached进程

root 13210 1 0 10:50 ? 00:00:00 /usr/local/memcached/bin/memcached -d -m 512 -u root -p 11211 -c 1024 -P /var/lib/memcached.11211pid

root 13218 2126 0 10:50 pts/0 00:00:00 grep --color=auto memcached

[root@mem-node1 ~]# lsof -i:11211

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME

memcached 13210 root 26u IPv4 34585 0t0 TCP *:memcache (LISTEN)

memcached 13210 root 27u IPv6 34586 0t0 TCP *:memcache (LISTEN)

memcached 13210 root 28u IPv4 34589 0t0 UDP *:memcache

memcached 13210 root 29u IPv4 34589 0t0 UDP *:memcache

memcached 13210 root 30u IPv4 34589 0t0 UDP *:memcache

memcached 13210 root 31u IPv4 34589 0t0 UDP *:memcache

memcached 13210 root 32u IPv6 34590 0t0 UDP *:memcache

memcached 13210 root 33u IPv6 34590 0t0 UDP *:memcache

memcached 13210 root 34u IPv6 34590 0t0 UDP *:memcache

memcached 13210 root 35u IPv6 34590 0t0 UDP *:memcache

[root@mem-node1 ~]# telnet 192.168.9.77 11211 //测试Memcached连接

Trying 192.168.9.77...

Connected to 192.168.9.77.

Escape character is '^]'.

quit

Connection closed by foreign host.

[root@mem-node1 ~]#

8.2.5配置Session共享

MSM目前可以在Tomcat6、7、8版本中使用, 并且支持Memcached会话故障转移。使用MSM配置Session共享需要提前下载MSM的类库文件到/usr/local/src目录下。Session共享配置需要在tomcat-node1与tomcat-node2两台主机上都进行操作,下面以tomcat-node1进行操作演示。

[root@tomcat-node1 ~]# mkdir /usr/local/src/MSM_Software

[root@tomcat-node1 ~]# cd /usr/local/src/MSM_Software

[root@tomcat-node1 MSM_Software]# ll

总用量 1212

-rw-r--r-- 1 root root 53259 8月 27 09:53 asm-5.2.jar

-rw-r--r-- 1 root root 323740 8月 27 09:51 kryo-4.0.0.jar

-rw-r--r-- 1 root root 85217 8月 27 09:51 kryo-serializers-0.38.jar

-rw-r--r-- 1 root root 152401 8月 27 09:49 memcached-session-manager-1.9.7.jar

-rw-r--r-- 1 root root 10788 8月 27 09:49 memcached-session-manager-tc8-1.9.7.jar

-rw-r--r-- 1 root root 5711 8月 27 09:52 minlog-1.3.0.jar

-rw-r--r-- 1 root root 37160 8月 27 09:51 msm-kryo-serializer-1.9.7.jar

-rw-r--r-- 1 root root 51287 8月 27 09:53 objenesis-2.4.jar

-rw-r--r-- 1 root root 20883 8月 27 09:52 reflectasm-1.11.3.jar

-rw-r--r-- 1 root root 472838 8月 27 09:50 spymemcached-2.12.2.jar

[root@tomcat-node1 MSM_Software]# cp -rf /usr/local/src/MSM_Software/* /usr/local/tomcat8/lib/

接下来进行序列化Tomcat配置,序列化Tomcat配置的方法有很多种:java默认序列化tomcat配置、javolution序列化tomcat配置、xstream序列化tomcat配置、flexjson序列化tomcat配置和kryo序列化tomcat配置。Tomcat官网介绍说使用kryo序列化Tomcat的效率最高,所以这里只介绍使用kryo序列化。

在Non-Sticky模式和Sticky模式下context.xml文件配置也有所不同(一般用的是Non-Sticky模式),本实验采用Non-Sticky模式,只需要修改conf/context.xml文件即可。

[root@tomcat-node1 MSM_Software]# cd /usr/local/tomcat8/conf/

[root@tomcat-node1 conf]# cp context.xml context.xml.bak

[root@tomcat-node1 conf]# vim context.xml

//在<Context>和</Context>之间添加下面内容.就在底部</Context>之前添加就行

<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"

memcachedNodes="n1:192.168.9.77:11211 n2:192.168.9.79:11211"

lockingMode="auto"

sticky="false"

sessionBackupAsync="false"

sessionBackupTimeout= "1000"

copyCollectionsForSerialization="true"

requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"

transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"

/>

[root@tomcat-node1 conf]# /usr/local/tomcat8/bin/shutdown.sh

[root@tomcat-node1 conf]# lsof -i:8080

[root@tomcat-node1 conf]# /usr/local/tomcat8/bin/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

Using CLASSPATH: /usr/local/tomcat8/bin/bootstrap.jar:/usr/local/tomcat8/bin/tomcat-juli.jar

Tomcat started.

[root@tomcat-node1 conf]# lsof -i:8080

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME

java 11915 root 58u IPv6 36201 0t0 TCP *:webcache (LISTEN)

tomcat-node2主机也需要依次执行上述的操作。

访问并按ctrl+F5刷新页面,发现Session信息会发生改变,但是Session ID不会改变,说明Session实现了共享。如图8.4所示,当前Session ID保存到了Memcached n1节点上。

至此Tomcat的Session共享已配置完成。

标签: #nginxtomcat会话保持