这章要演示的东西比较多,Sad!一步一步来,不要急。
一、使用Nginx代理,访问我们两个Tomcat的应用,每个Tomcat都有自己的Session。通过Nginx做负载均衡,访问Tomcat应用的搭建过程,请参照:第一讲—Nginx入门实战
二、为了区别负载均衡后,我们需要新建一个Web应用,写一个Servlet,打印当前应用名称,时间,和SessionID。为了区分来自不同的应用,Servlet我们要区分出来,打两次war包
第一个打包的Servlet的打印信息如下,打成war包,放到Tomcat1下
out.println("Tomcat_One " + new SimpleDateFormat("yyyy-MM-dd mm:HH:ss").format(new Date()) + " sessionId----->" + session.getId());
第二个打包的Servlet的打印信息为:,打成war包,放到Tomcat2下
out.println("Tomcat_Two " + new SimpleDateFormat("yyyy-MM-dd mm:HH:ss").format(new Date()) + " sessionId----->" + session.getId());
package com.minutch;
import
java.io.IOException;
import
java.io.PrintWriter;
import
java.text.SimpleDateFormat;
import
java.util.Date;
import
javax.servlet.ServletException;
import
javax.servlet.annotation.WebServlet;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
javax.servlet.http.HttpSession;
@WebServlet(
"/GetInfoServlet"
)
public class GetInfoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public GetInfoServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
PrintWriter out = response.getWriter();
out.println(
"Tomcat_One "
+ new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
).
format
(new Date()) +
" sessionId----->"
+ session.getId());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
|
三、我们不改变Tomcat 的任何配置,也不持久化Session,也不接入Redis,先看看效果(注意:为了达到轮流访问两个Tomcat的应用,Nginx不配置任何分发策略,默认就是轮询方式)
3.1 效果:
访问Servlet第一次,结果如下:Tomcat_One 2015-04-02 19:19:03 sessionId----->1CD5F28AE679A83B3B089BB672EE4BE6
访问Servlet第二次,结果如下:Tomcat_Two 2015-04-02 19:19:05 sessionId----->2FDSF25ACF39A85F6F3LICB653SD3CF7
访问Servlet第三次,结果如下:Tomcat_One 2015-04-02 19:19:10 sessionId----->D78714263D498E4316E0F7199BC39896S
访问Servlet第四次,结果如下:Tomcat_Two 2015-04-02 19:19:18 sessionId----->634AE2CC6E6AEC18F154B9A2BE2863F2
3.2 分析
通过结果,我们可以发现,Nginx会轮流把请求发到两个Tomcat上,但是我明明在同一个浏览器,同一个页面发的请求,为什么SessionId每次都在变化呢,看下面的解释?
第一次请求,访问Tomcat1,Tomcat1后台生成一个Session,这时,返回前端一个SessionId,假设为SessionIDA。
第二次请求,访问Tomcat2,这个请求会把SessionIDA传到Tomcat2的后台,寻找是否存在SessionID为SessionIDA的Session,显然是找不到的,于是Tomcat2生成一个新的Session,并把SessionID返回前端,假设SessionID为SessionIDB。
第三次请求,访问Tomcat1,这次请求会把SessionIDB传到Tomcat1的后台,寻找是否存在SessionID为SessionIDB的Session,此时Tomcat1只有SessionIDA的Session,所以也不能找到,于是生成一个新的Session,SessionID为SessionIDC,返回到前端,然后开始循环这个操作,这样就可以解释上面的结果了。
四、我们仍然不改变Tomcat的任何配置,也不持久化Session,也不接入Redis,但是Nginx稍微有点变化,我们在Nginx.conf的配置文件加了一点东西,具体往下看
upstream saint {
server 127.0.0.1:9000;
server 127.0.0.1:9001;
ip_hash;
#加了这个配置,根据IP来分发请求,也就是相同的IP会发到同一个Tomcat上,我们来看看效果
}
|
用同一个浏览器,多次访问Servlet
4.1 效果
第一次请求:Tomcat_Two 2015-04-02 19:25:10 sessionId----->21C1E68E0A142A205E8DCD87C2D13188
第二次请求:Tomcat_Two 2015-04-02 19:25:15 sessionId----->21C1E68E0A142A205E8DCD87C2D13188
第三次请求:Tomcat_Two 2015-04-02 19:25:19 sessionId----->21C1E68E0A142A205E8DCD87C2D13188
4.2 分析
都是一样的,因为相同的IP发到同一台Tomcat2上,后台产生的SessionId返回到前端,前端在次访问时,通过这个SessionID是能找到Session的,所以不会创建新的Session。
五、来点刺激的,Tomcat的Session共享,把Session迁移到Redis中,然后我们把Nginx的那个ip_hash配置去掉。
Tomcat的Session配置在第一讲后半段提过,这里再写一次。
5.1 启动Redis服务器,使用默认端口
src
/redis-server
|
5.2 配置Tomcat持久化Session到Redis需要的jar (版本不对可能会报classNotFoundException,我开始用commons-pool-2.3.jar,jredis-1.0rc.jar,都不行)
commons-pool-1.6.jar,
jedis-2.1.0.jar
tomcat-redis-session-manager-1.2-tomcat-7-java-7.jar
将上面三个jar放到tomcat1,和tomcat2的lib目录下
5.3 配置Tomcat'的content.xml文件,详情如下
<
Context
>
<!-- Default set of monitored resources -->
<
WatchedResource
>WEB-INF/web.xml</
WatchedResource
>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<!-- Session持久化到文件的配置
<Manager className="org.apache.catalina.session.PersistentManager">
debug=0
saveOnRestart="true"
maxActiveSession="-1"
minIdleSwap="-1"
maxIdleSwap="-1"
maxIdleBackup="1"
<Store className="org.apache.catalina.session.FileStore"
directory="/Users/Minutch/tomcatSession"
/>
</Manager>
-->
<
Valve
className
=
"com.radiadesign.catalina.session.RedisSessionHandlerValve"
/>
<!--Redis配置-->
<
Manager
className
=
"com.radiadesign.catalina.session.RedisSessionManager"
host
=
"localhost"
port
=
"6379"
database
=
"0"
maxInactiveInterval
=
"10"
/>
<!-- Uncomment this to enable Comet connection tacking (provides events
on session expiration as well as webapp lifecycle) -->
<!--
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
-->
</
Context
>
|
5.4 配置Nginx.conf ,去掉ip_hash这个配置项,比较一下我们的变化,和第一次试验的时候相比,我们仅仅是增加了持久化Session到Redis的配置,那结果会怎么样呢,请往下看。
效果:
第一次请求结果:Tomcat_One 2015-04-02 19:32:30 sessionId----->D78714263D498E4316E0F7199BC39896
第二次请求结果:Tomcat_Two 2015-04-02 19:33:10 sessionId----->D78714263D498E4316E0F7199BC39896
第三次请求结果:Tomcat_One 2015-04-02 19:33:34 sessionId----->D78714263D498E4316E0F7199BC39896
第四次请求结果:Tomcat_Two 2015-04-02 19:33:47 sessionId----->D78714263D498E4316E0F7199BC39896
第五次请求结果:Tomcat_One 2015-04-02 19:34:08 sessionId----->D78714263D498E4316E0F7199BC39896
分析:一开始叫我分析这个结果,其实我是拒绝的,因为如果我说的这个结果是假的,会在后期给我加特效,看官们自己看完学完发现不是这样的,那我就是在作假。所以我把所有流程走了一遍,做完之后,Duang的一下,发现结果真的是这样,他们使用了相同的Session了,也就是说,Tomcat1在接收到请求时,创建Session之后,会把Session持久化到Redis,而此时,Tomcat2也会取Redis里的Session数据,所以当请求访问Tomcat2的时候,也就有了Tomcat1里的Session,所以打印出来的SessionId是一样的。
(具体Session如何持久化到Redis,另一个Tomcat如何获取Redis里的Session,何时获取Redis的Session,还需要有时间的时候再去研究,以上的言论,都是根据结果反推的,如有错误之处,恳请指出,以免误导到更多人——By Minutch)