在nginx实现了负载均衡之后,用户第一次请求的tomcat和第二次请求的tomcat基本不是同一个,但是你在第一次请求放在session中的值只有一个tomcat1才有,第二个请求的那个tomcat2里面是没有的。这样就出现了用户不停登入的情况。为了解决这个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的共享
暂未学习,学习之后再加入。
来源:oschina
链接:https://my.oschina.net/u/4386227/blog/4906347