代码之家  ›  专栏  ›  技术社区  ›  Rich

确定Tomcat中数百个AJP线程的原因

  •  3
  • Rich  · 技术社区  · 16 年前

    今天早上,一台Tomcat机器在我们机器的8个核中的6个核上使用了100%的CPU。我们使用JConsole进行了一个堆转储,然后尝试连接JVisualVM来获取一个概要文件,以查看占用所有CPU的内容,但这导致Tomcat崩溃。至少我们有垃圾堆!

    我已经将堆转储加载到Eclipse MAT中,在那里我发现有565个java.lang.Thread线程. 其中一些,显然是完全合法的,但绝大多数被命名为“ajp-6009-XXX”,其中XXX是一个数字。

    我对Eclipse MAT很熟悉,但还没有找到解释。如果有人有一些关于Tomcat为什么要这么做的建议,或者一些关于为什么要使用Eclipse MAT的提示,那将不胜感激!

    2 回复  |  直到 16 年前
        1
  •  1
  •   Chad    16 年前

    我想这并不是一个直接的答案,但是作为生产中的一种缓解方法,您可以通过在您的配置中限制AJP的maxThreads来限制损害 http://tomcat.apache.org/tomcat-6.0-doc/config/ajp.html

    默认值是200,这当然是很多线程-但这可能无法解释上面的565。很明显,这有可能将问题推到其他地方,但是也许您可以更好地在那里调试问题,或者它将以不同的方式表现出来。有没有可能你只是承受了很大的压力?在导致您遇到问题的时期,Apache的行为有什么值得注意的地方吗?

        2
  •  0
  •   rhu    16 年前

    在我们的例子中,每根线都卡在里面 java.util.HashMap 在get()方法中,在for循环中紧密旋转:

       public V get(Object key) {
           if (key == null)
               return getForNullKey();
           int hash = hash(key.hashCode());
           for (Entry<K,V> e = table[indexFor(hash, table.length)];
                e != null;
                e = e.next) {
               Object k;
               if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                   return e.value;
           }
           return null;
       }
    

    我们的理论是,不知何故,特定bucket的条目链表已经损坏,并且指向自身,因此无法退出循环。由于没有完成任何作业,因此随着请求的增多,池中的线程也越来越多。

    检查是否有共享的 HashMap (或 HashSet )其中几个线程可以同时访问。如果是这样,而且很容易做到,要么用 ConcurrentHashMap ,或使用 ReentrantReadWriteLock Collections.synchronizedMap() 当然,但这不会是可伸缩的。

    另请参见:

    http://lightbody.net/blog/2005/07/hashmapget_can_cause_an_infini.html http://mailinator.blogspot.com/2009/06/beautiful-race-condition.html

    推荐文章