集群中Web页面分批输出的问题

为了提高性能和减少用户等待时间,我们常用response.flushBuffer方法来分批输出已经转换好的页面。这样内容可以分块逐步显示在网页上,用户不用长时间面对一个空白的页面等待。但在集群系统中,当某个服务器瘫痪从而引起服务迁移情况下,问题就来了,用户可能会看到重复的内容。

 

这里我们做个实验,写如下一段代码:

      response.setContentType("text/html");
      response.setContentLength(500);

 

        //不同的机器用不同的颜色和名字

        String color=this.getInitParameter("Color");
        String server=this.getInitParameter("Server");
       
        PrintWriter writer = response.getWriter();
        writer.println("<html><body>");
        writer.println("<h1><font color=/"" + color + "/">Session serviced by tomcat " + server + "</font></h1>");
       
        writer.println("<table aligh=/"center/" border=/"1/">");
        writer.println("<tr><td>Session ID</td><td>");
        writer.println(request.getSession(true).getId());
        writer.println("</td>");
               
        writer.println("</tr><tr><td>Created on</td><td>");
        writer.println(request.getSession().getCreationTime());
        writer.println("</td></tr></table>");
       
        writer.println("<form method=/"POST/" action=/"LongTask/">");
        writer.println("<Input name=/"test/" value=/"/">");
        writer.println("<INPUT TYPE=submit name=/"submit/" value=/"update/">");
        writer.println("</form>");

 

        //提前把前面的内容输出

        writer.flush();

 

        Object ob = request.getParameter("test");
        if (ob!=null) {
            request.getSession().setAttribute("test",ob);
            try {
                String time=this.getInitParameter("WaitTime");

                  //这里模拟一个长时间的任务,以便有机会手动把一个机器停掉
                Thread.sleep(Integer.parseInt(time));
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }       
        }
        writer.println(request.getSession().getAttribute("test"));
        writer.flush();
        writer.close();

        writer.println("</body></html>");

 

我们用Apache 2.2 + mod_jk + Tomcat 6.0 (In-memory session replication)来架设集群。注意要在httpd.conf的配置中设置Flush选项:

JkWorkersFile conf/workers.properties
JkOptions +FlushPackets
JkMount /examples/jsp/* bal1
JkMount /jkstatus/ stat1

mod_jk的配置

worker.list = bal1,stat1

worker.Tomcat6A.type = ajp13
worker.Tomcat6A.host = localhost
worker.Tomcat6A.port = 8009
worker.Tomcat6A.lbfactor = 10

worker.Tomcat6B.type = ajp13
worker.Tomcat6B.host = localhost
worker.Tomcat6B.port = 8010
worker.Tomcat6B.lbfactor = 10

worker.Tomcat6C.type = ajp13
worker.Tomcat6C.host = localhost

worker.Tomcat6C.port = 8011
worker.Tomcat6C.lbfactor = 10

worker.bal1.type = lb
worker.bal1.sticky_session = 1
worker.bal1.balance_workers = Tomcat6A, Tomcat6B, Tomcat6C

worker.stat1.type = status

 

我们把上段代码编译成名字为LongTask的servlet,并放到Tomcat自带的例子examples下面。架设三个Tomcat实例在三台机器上。(本文为了方便都放到一台机器localhost上)。当一台机器正在处理请求时,我们手动停掉它。测试结果如下:

 

 

图1:发生故障前

 

图2:发生故障后

 

除了数据重复外,Session数据也丢失了(原因还未知). 但如果关闭分批输出,则没有这些问题.

发布了34 篇原创文章 · 获赞 1 · 访问量 14万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览