当前位置:  开发笔记 > 编程语言 > 正文

Apache/Tomcat错误 - 正在传递错误的页面

如何解决《Apache/Tomcat错误-正在传递错误的页面》经验,为你挑选了1个好方法。

这个错误一直让我疯狂.我们有一台运行Apache和Tomcat的服务器,服务于多个不同的站点.通常情况下,服务器运行正常,但有时会发生错误的时候,人们都提供了错误的页面- 页面是别人请!

线索:

正在传递的页面是另一个用户最近请求的页面,并以其他方式正确传递.众所周知,要同时交换两个请求.据我所知,没有错误传递的页面超过几分钟.

它只影响Tomcat提供的文件.像图像这样的静态文件不受影响.

它不会一直发生.当它确实发生时,它发生在每个人身上.

它似乎发生在需求高峰时期.然而,需求还不是很高 - 它肯定在Apache可以应付的范围内.

重启Tomcat修复了它,但只有几分钟.重新启动Apache修复它,但只有几分钟.

服务器使用Gentoo上的Java 6 VM运行Apache 2和Tomcat 6.连接是使用AJP13,并且块JkMount内的指令是正确的.

任何日志文件都没有用处.


更多的信息:

Apache没有打开任何形式的缓存.httpd.conf和相关导入中的所有与缓存相关的条目都说明,例如:


  LoadModule cache_module modules/mod_cache.so

虽然Apache的选项不包含该标志:

APACHE2_OPTS="-D DEFAULT_VHOST -D INFO -D LANGUAGE -D SSL -D SSL_DEFAULT_VHOST -D PHP5 -D JK"

Tomcat同样没有打开缓存选项,我可以找到.

toolkit的建议很好,但在这种情况下不合适.是什么让我相信错误不在我自己的代码中是因为它不仅仅是一些正在传输的值 - 它是整个请求,包括URL,参数,会话cookie,整个事情.人们正在回复说"你以约翰身份登录",而他们显然没有.


更新:

根据几个人的建议,我将向Tomcat提供的页面添加以下HTTP标头,以禁用所有形式的缓存:

Cache-Control: no-store
Vary: *

希望这些标题不仅受到Apache的尊重,还受到可能阻碍的任何其他缓存或代理的尊重.不幸的是我无法故意重现这个错误,所以我只能等待,看看它是否再次出现.

我注意到包含以下标题 - 它们是否可能以任何方式相关?

Connection: Keep-Alive
Keep-Alive: timeout=5, max=66

更新:

显然,当我睡着的时候,这又发生了,但现在已经停止了,我很清醒地看到了它.再一次,在我看到的日志中没有任何用处,所以我没有找到实际发生的事情或如何防止它的线索.

我可以在Apache或Tomcat的日志中添加任何额外的信息,以便更容易诊断吗?


更新:

由于这已经发生了几次,我们已经改变了Apache连接到Tomcat的方式,看它是否会影响事物.我们正在使用这样mod_jk的指令:

JkMount /portal ajp13

我们现在切换到使用mod_proxy_ajp,如下所示:

ProxyPass /portal ajp://localhost:8009/portal

我们会看看它是否有所作为.这个错误总是令人烦恼地无法预测,所以我们永远无法明确地说它是否有效.


更新:

我们刚刚在一个使用的网站上得到了错误mod_jk,而同一服务器上使用的姐妹网站mod_proxy_ajp没有显示错误.这并不能证明任何事情,但它确实提供了证据,表明转职mod_proxy_ajp可能有所帮助.


更新:

我们昨晚在一个使用的网站上再次收到错误mod_proxy_ajp,显然没有解决它 - mod_jk不是问题的根源.我将尝试关闭持久连接的匿名建议:

KeepAlive Off

如果这也失败了,我将非常绝望地开始调查GlassFish.


更新:

该死!问题刚刚回来.我有一段时间没有看到它,所以我开始认为我们最终将它排序了.我讨厌heisenbugs.



1> toolkit..:

它可能是你的servlet的线程安全吗?

您的servlet是否在实例成员中存储任何信息.

例如,以下简单的内容可能会导致与线程相关的问题:

public class MyServlet ... {
    private String action;

    public void doGet(...) {
         action = request.getParameter("action");
         processAction(response);
    }

    public void processAction(...) {
         if (action.equals("foo")) {
             // send foo page
         } else if (action.equals("bar")) {
             // send bar page
         }
     }
}

因为serlvet是由多个线程访问的,所以不能保证动作实例成员不会被某个elses请求破坏,并最终返回错误的页面.

这个问题的简单解决方案是使用实例成员的局部变量insead:

public class MyServlet ... {
    public void doGet(...) {
         String action = request.getParameter("action");
         processAction(action, response);
    }

    public void processAction(...) {
         if (action.equals("foo")) {
             // send foo page
         } else if (action.equals("bar")) {
             // send bar page
         }
     }
}

注意:如果您为他们的视图分派它们,这也扩展到JavaServer Pages?

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有