在nginx实现了负载均衡之后,用户第一次请求的tomcat和第二次请求的tomcat基本不是同一个,但是你在第一次请求放在session中的值只有一个tomcat1才有,第二个请求的那个tomcat2里面是没有的。这样就出现了用户不停登入的情况。为了解决这个session共享的问题,于是我们提出了以下几个方案:
文章目录
- nginx实现session共享
- ip_hash(ip绑定)
- 步骤实现
- 大致描述
- 优缺点
- tomcat集群实现session的共享
- 步骤实现
- 创建一个web项目
- 复制一份tomcat到文件夹中
- 导出war包
- 修改server.xml
- 修改端口及工作路径
- 启动tomcat
- 修改nginx配置文件
- 测试是否成功
- 关闭nginx
- 优缺点
- redis实现session的共享
nginx实现session共享
ip_hash(ip绑定)
原理:每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
步骤实现
大致描述
直接在配置文件里面添加ip_hash 则可以实现ip绑定,ip绑定 和什么浏览器没有关系,是和本机电脑ip有关系,A B 两个客户端,如果 nginx配置ip绑定以后 A 客户端如果请求的 是8080 服务器,则以后来自客户端的A 的请求都将交给8080服务器处理,如果是IP 绑定,在高并发的情况下,也没有什么作用,但是 ip绑定可以实现 会话共享
upstream backserver {
ip_hash;server 192.168.0.14:88;server 192.168.0.15:80;
}
优缺点
优点:实现也比较简单,需要修改一下nginx的配置文件即可
缺点:
- 一大堆人连同一个网访问的时候,就没有负载均衡这一说了,这一大堆的ip都是一样,都去访问同一个tomcat。
- 如果这个人访问的tomcat突然挂了,那nginx的故障转移机制将会分发给另一个tomcat服务器,这样一来所有请求这个tomcat的所有用户就又需要重新登入了。
- 如果这个人用着用着突然在用的网络不稳定,然后这个人换了另一个网,这样ip一换,这个人又要重新登入了。
小结:这样的解决方案能简单的实现,但是不能满足商业需求。
tomcat集群实现session的共享
原理:这个方法原理比较简单,就是有几个tomcat,就复制了几个session,比如一个tomcat的session发生了改变,其余tomcat的session也会复制发生改变,保证了用户的session在所有的tomcat中都是相同的。
步骤实现
创建一个web项目
在起始页index.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> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> SessionID:<%=session.getId()%> <BR> SessionIP:<%=request.getServerName()%> <BR> SessionPort:<%=request.getServerPort()%> <% out.println("This is Tomcat Server 111"); %> </body>
</html>
记得修改一下输出语句,进行不同tomcat的区分
写入之后,在web.xml中添加一个<distributable/>
节点,放在display下面
复制一份tomcat到文件夹中
(文件夹用于储存tomcat)
两个tomcat内容都是一样的,只不过文件夹命名不一样
导出war包
放到tomcat的的webapps中
导出两次,第二次的时候,把输出语句换成2222,以便于观察,把第二次导出的war包放入到tomcat2中,第一次的就是放在tomcat1中。
修改server.xml
打开tomcat的conf文件夹,对server.xml文件修改
找到<Engine name="Catalina" defaultHost="localhost">
这一条语句,在此语句后输入:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> <Channel className="org.apache.catalina.tribes.group.GroupChannel"> <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender> <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> </Channel> <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/> <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/> <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster>
修改端口及工作路径
修改端口
打开tomcat的conf文件夹,对server.xml文件修改,修改成不一样的即可,我为了简便,修改为如下:
tomcat1:
tomcat2:
修改工作路径
打开tomcat的bin文件夹,对startup.bat文件修改
在@echo off
前面加上:
set TLTLE="tomcat002"
set CATALINA_BASE="D:\tomcat_cluster\tomcat002"
set CATALINA_HOME="D:\tomcat_cluster\tomcat002"
记得两个tomcat都要修改
启动tomcat
两个都要启动(忽略乱码问题)
修改nginx配置文件
修改conf路径下的nginx.conf文件
- 第一个参数为为自己的tomcat地址
- weight:权重
- fail_timeout:失败时间
- max_fails:失败次数
fail_timeout与max_fails可以理解为,在fail_timeout的时间内,失败max_fails次,那就把请求分配给其他服务器
测试是否成功
在浏览器输入自己的url以及端口测试
测试成功:是两个不同的tomcat,但是是一样的session,session共享成功
关闭nginx
再次进入已经显示进不去了,证明nginx关闭了
优缺点
优点:实现简单,没有什么花里胡哨的操作。如果集群中的tomcat的个数不多,而且用户没有那么多的时候可以选择这种方式。
缺点:只要Session数据有变化,就需要将数据同步到所有其他机器上,机器越多,同步带来的网络带宽开销就越大;当用户很多时,每台机器用于保存Session数据的内容占用会很严重。
redis实现session的共享
暂未学习,学习之后再加入。