2010-01-29 4 views
3

아파치가있는 두 개의 Tomcat 6.0.20 서버가 있는데 두 서버 사이에 AJP를 사용하여 통신합니다. Tomcat은 차례대로 JBoss 클러스터에서 웹 서비스를 사용합니다.Tomcat에서 수백 개의 AJP 스레드의 원인을 확인하십시오.

오늘 아침 Tomcat 머신 중 하나가 우리 머신의 8 코어 중 6 코어에서 100 % CPU를 사용하고있었습니다. 우리는 JConsole을 사용하여 힙 덤프를 취한 다음 JVisualVM을 연결하여 모든 CPU를 차지하는 프로파일을 얻으려고했지만 Tomcat이 충돌하게되었습니다. 적어도 힙 덤프가 있었어!

이클립스 MAT에 힙 덤프를로드했습니다. 여기에서 java.lang.Thread의 인스턴스가 565 개 있다는 것을 알았습니다. 이 중 일부는 분명히 완전히 합법적이지만, 대다수의 이름은 "ajp-6009-XXX"이며 XXX는 숫자입니다.

이클립스 매트 (Eclipse MAT)를 잘 알고 있지만 설명을 찾을 수 없습니다. Tomcat이 왜이 작업을 수행하고 있는지 또는 Eclipse Mat을 사용하는 이유를 알아내는 데 도움이 될만한 지침이 있다면 누구나이 점을 인정할 것입니다.

+1

힙 덤프가 사망 한 스레드의 유물을 포함 할 수 있으므로 모든 565의가 고장이 발생할 때 활성화되었을 수 있습니다. – skaffman

답변

1

이것은 직접적인 대답은 아니지만 프로덕션 환경에서의 완화 방법으로, http://tomcat.apache.org/tomcat-6.0-doc/config/ajp.html에 대해 구성에서 AJP에 대한 maxThreads를 제한하여 피해를 제한 할 수 있습니까?

기본값은 200입니다. 이는 많은 스레드입니다.하지만 위의 565에 대해서는 설명하지 않았을 수 있습니다. 분명히 그 문제는 다른 곳에서 문제를 푸는 잠재력을 가지고 있지만 아마도 문제를 거기에서 디버깅 할 수있을 것입니다. 그렇지 않으면 다른 방식으로 나타납니다. 당신은 바로 부하가 높을 가능성이 있습니까? 발생한 문제에 이르는 기간에 Apache의 동작에 주목할만한 것이 있습니까?

0

스레드 덤프를 얻을 수 없다면 확실하게 알 수 없지만 8 개의 코어가 모두 100 % 스레드로 수천 개의 스레드로 바쁜 비슷한 문제가 발생한 적이 있습니다 (그러나 Tomcat이 아니 었습니다).

우리의 경우

, 각 스레드는 루프에 대해 단단히 회전, 가져 오기() 메소드에 java.util.HashMap 안에 갇혀 있었다 : 우리의 이론은 특정 버킷의 항목 어떻게 든 연결리스트가 있다고했다

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; 
    } 

손상되어 스스로를 가리키고 있었으므로 루프를 빠져 나올 수 없었습니다. 작업이 끝나지 않아 요청이 많아짐에 따라 풀에서 점점 많은 스레드가 소비되었습니다.

새 항목을 삽입하는 동안 테이블의 크기를 조정해야하지만 여러 스레드에서 읽기/쓰기 액세스가 보장되지 않는 경우 발생할 수 있습니다. 하나의 스레드가 특정 버킷 위치에서 연결된 목록을 확장하는 반면 다른 스레드는 연결된 목록을 이동하려고하면 바쁠 수 있습니다. 해시 맵에 대한 액세스가 동기화되지 않으면 일반적으로 재사용 할 수 없지만 손상 될 가능성이 큽니다.

여러 스레드가 동시에 액세스 할 수있는 공유 된 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

관련 문제