zk+redis+tomcat 实现session共享遇到问题

实现目的:
在使用Nginx+Tomcat+zk项目实现负载均衡的时候,由于Nginx对不同的请求分发到某一个Tomcat,Tomcat在运行的时候分别是不同的容器里,因为会出现session不同步或者丢失的问题。

通过tomcat+redis+zk项目实现session共享

一、服务器环境配置
tomcat 版本7.0.62
redis 版本 3.0.1
jdk 版本 1.7.0_79
二、tomcat 下面配置 安装配置redis
将tomcat-redis-session-1.0-SNAPSHOT.jar、jedis-2.7.2.jar、commons-pool2-2.0.jar 三个jar包放在tomcat1实例下的lib目录下。

三、修改tomcat实例下conf/contex.xml文件

 <?xml version='1.0' encoding='utf-8'?>  
<Context>  
    <WatchedResource>WEB-INF/web.xml</WatchedResource>  
    <!-- tomcat-redis-session共享配置 -->  
    <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />  
        <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"  
         host="192.168.0.159"   
         port="6379"   
         database="0"   
         maxInactiveInterval="60" />  

</Context>     

四、部署zk项目到tomcat zk项目源码下载

五、启动redis——启动tomcat ——访问登录界面

1.输入完用户名密码点击登录后发现 当前界面失效了。
![点击登录结果查询不到这个界面了](https://img-blog.csdnimg.cn/img_convert/448eaa5bde6e3d84b683e25bba9a0317.png
2.然后就查看zk的配置,发现每次请求会被DHtmlLayoutServlet拦截
web.xml

 <servlet>
    <description>ZK loader for ZUML pages</description>
    <servlet-name>zkLoader</servlet-name>
    <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>
    <init-param>
      <param-name>update-uri</param-name>
      <param-value>/zkau</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
<servlet-mapping>
    <servlet-name>zkLoader</servlet-name>
    <url-pattern>*.zul</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>zkLoader</servlet-name>
    <url-pattern>*.zhtml</url-pattern>
  </servlet-mapping>

3.打开 DHtmlLayoutServlet源码通过调试发现
初始化界面的时候回去判断当前页面是否有创建一个Desktop ,如果通过key在缓存中找不到这个Desktop 就会新增一个Desktop 。

protected boolean process(Session sess,
	HttpServletRequest request, HttpServletResponse response, String path,
	boolean bRichlet)
	throws ServletException, IOException {
		final WebApp wapp = sess.getWebApp();
		final WebAppCtrl wappc = (WebAppCtrl)wapp;
		final Configuration config = wapp.getConfiguration();

		final boolean bInclude = Servlets.isIncluded(request);
		final boolean compress = _compress && !bInclude;
		final Writer out = compress ? (Writer)new StringWriter(): response.getWriter();
		final DesktopRecycle dtrc = bInclude ? null: config.getDesktopRecycle();
		final ServletContext ctx = getServletContext();
		Desktop desktop = dtrc != null ?
			DesktopRecycles.beforeService(dtrc, ctx, sess, request, response, path): null;

		try {
			if (desktop != null) { //recycle
				final Page page = Utils.getMainPage(desktop);
				if (page != null) {
					final Execution exec = new ExecutionImpl(
						ctx, request, response, desktop, page);
					WebManager.setDesktop(request, desktop);
					wappc.getUiEngine().recycleDesktop(exec, page, out);
				} else
					desktop = null; //something wrong (not possible; just in case)
			}
			if (desktop == null) {
				//如果不存在desktop 就会新建一个 desktop 
				desktop = _webman.getDesktop(sess, request, response, path, true);
			.......
	}

创建的desktop  会被添加到SimpleDesktopCache._desktops 缓存当中去。
private final Cache _desktops;
//添加新的桌面到缓存 _desktops
public void addDesktop(Desktop desktop) {
		final boolean added;
		final Desktop old;
		synchronized (_desktops) {
			old = _desktops.put(desktop.getId(), desktop);
		}
		if (old != null) {
			_desktops.put((old).getId(), old); //recover
			log.warning(
				desktop == old ? "Register a desktop twice: "+desktop:
					"Replicated ID: "+desktop+"; already used by "+old);
		}
		//if (log.debugable()) log.debug("After added, desktops: "+_desktops);
	}
当输入完用户名密码之后点击登录按钮又会被DHtmlLayoutServlet所拦截,这次请求会通过之前存储桌面的id去查找缓存中是否还存在当前的desktop。

SimpleDesktopCache.getDesktopIfAny(String desktopId)
这里去通过id 无法查找到对应的桌面,zk就会认为当前页面已经失效,登录请求被中断。

这里写图片描述

问题总结:(由于对zk理解能力不够,描述不够专业还请多多谅解。)
不知道为什么tomact下面配置了redis后,zk项目的Desktop 就没有存储到缓存当中去了。
由于没有找到合适的zk项目session共享的方案,希望大家有成功案例的朋友告诉下如果去配置。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值