3

HAProxy 正在 ping Tomcat 并请求一个非常小的页面,导致 Tomcat 每 2 秒创建一个新会话。有没有办法以编程方式(或通过配置)告诉Tomcat不要为特定页面创建新会话?

4

5 回答 5

13

你不需要实现任何东西,它已经存在了;)!

Tomcat 容器提供Crawler Session Manager Valve(valve 就像 HttpServletFilter,但在 Tomcat 容器内部(较低级别)。您可以在此处找到更多详细信息http://tomcat.apache.org/tomcat-7.0-doc/config/valve.html #Crawler_Session_Manager_Valve

您只需通过适当的配置将<Valve>标记添加到您的 tomcat 的server.xml中。请记住为机器人用户代理提供正则表达式。

例如

<Valve className="org.apache.catalina.valves.CrawlerSessionManagerValve"
crawlerUserAgents=".*googlebot.\*|.*yahoo.*" sessionInactiveInterval="600"/>

可以查看valve的源码:http: //grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.11/org/apache/catalina/valves/ CrawlerSessionManagerValve.java

于 2012-11-21T14:56:02.927 回答
4

就在这里。这有点复杂,但对我们来说效果很好。

基本上,我们更改会话的过滤器链。我们为机器人(Google、Pear、Yahoo)这样做。

创建一个新的过滤器并注册它,然后将此源用于过滤器类:

public class BotFilter implements javax.servlet.Filter {
  private int inactive_seconds = 5*60;
  private String[] bots = new String[] { "googlebot", //google
    "msnbot", //msn
    "slurp", //yahoo
    "libcurl", //curl, sometimes used with bigbrother
    "bigbrother", //bigbrother availability check
    "whatsup", //whatsup availability check
    "surveybot", //unknown
    "wget", // nocomment
    "speedyspider", //http://www.entireweb.com/about/search_tech/speedyspider/
    "nagios-plugins", //Alle Nagios-Abfragen
    "pear.php.net", //Irgendwelcher PHP-Scheiß
    "mj12bot", //http://www.majestic12.co.uk/projects/dsearch/mj12bot.php
    "bingbot", //M$ Bing
    "dotbot", //We are just a few Seattle based guys trying to figure out how to make internet data as open as possible.
    "aggregator:spinn3r", //http://spinn3r.com/robot
    "baiduspider" //http://www.baidu.com/search/spider.htm
  };
  private HashMap<String, HttpSession> botsessions;

  public BotFilter() {
    this.botsessions = new HashMap<String, HttpSession>();
  }

  public void init(FilterConfig config) throws ServletException {

  }

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain next) throws IOException, ServletException {
    if (request instanceof HttpServletRequest) {
      HttpServletRequest httprequest = (HttpServletRequest) request;
      try {
        String useragent = ((HttpServletRequest) request).getHeader("User-Agent");
        if (useragent == null) {
          ((HttpServletResponse) response).sendRedirect("http://www.google.com");
        }
        useragent = useragent.toLowerCase();
        if (httprequest.getSession(false) == null) {
        }
        for (int i = 0; i < this.bots.length; i++) {
          if (useragent.indexOf(this.bots[i]) > -1) {
            String key = httprequest.getRemoteAddr() + useragent;
            boolean SessionIsInvalid=false;
            synchronized(this.botsessions) {
              try {
                if(this.botsessions.get(key)!=null)
                  this.botsessions.get(key).getAttributeNames();
              } catch (java.lang.IllegalStateException ise) {
                SessionIsInvalid = true;
              }
              if(this.botsessions.get(key)==null||SessionIsInvalid) {
                httprequest.getSession().setMaxInactiveInterval(this.inactive_seconds);
                if(SessionIsInvalid)
                  this.botsessions.remove(key); //Remove first, if in there
                this.botsessions.put(key, httprequest.getSession()); //Then add a little spice
              } else {
                next.doFilter(new BotFucker(httprequest, this.botsessions.get(key)), response);
                return;
              }
            }
          };
        }
      } catch (Exception e) {
        //Error handling code
      }
    }
    next.doFilter(request, response);
  }

  public void destroy() {

  }
}

还有这个重定向类的小东西:

public class BotFucker extends HttpServletRequestWrapper {

  HttpSession session;

  public BotFucker(HttpServletRequest request, HttpSession session) {
    super(request);
    this.session = session;
  }
  @Override
  public HttpSession getSession(boolean create) {
    return this.session;
  }
  @Override
  public HttpSession getSession() {
    return this.session;
  }
}

如果它们在给定的时间限制内使用相同的 IP 再次连接,这两个类会重新使用机器人之前的会话。我们不能 100% 确定这对机器人接收到的数据有什么影响,但由于这段代码现在已经运行了好几个月并解决了我们的问题(来自谷歌的每个 IP 每秒多个连接/会话)。

在有人尝试提供帮助之前:该问题已通过网站管理员界面多次提交给 Google。抓取间隔已降低到可能的最低设置,并且该问题在适当的论坛上产生了 3x 回复线程,但没有任何提示说明此问题存在的原因。

于 2011-10-10T09:28:03.713 回答
3

不要将其指向您的应用程序页面。如果 httpchk 正在拉动一个 JSP 页面,它将创建一个会话。

您可以将 HAProxy 指向您的 httpchk 的静态 HTML 页面吗?

或者,创建一个 servlet 来检查您需要验证的任何运行状况,但不创建会话。(à la HttpServletRequest.getSession(false))

于 2011-10-10T03:19:39.667 回答
2

只需session=false在 JSP 中添加指令。

<%@ page session="false"%>
于 2013-04-19T15:36:11.970 回答
1

此页面是常规 Web 应用程序还是独立 Web 应用程序的一部分?

如果该页面是独立 Web 应用程序的一部分,即该应用程序中仅存在该页面,您可以在该应用程序的 web.xml 中设置低会话超时。Liek 2 分钟甚至更低。

否则,在Tomcat端没有解决你的问题。如果较早的会话 ID 没有随请求一起发送,Tomcat 将创建一个新会话。

于 2011-10-10T09:16:17.667 回答