300 회 연결 후 Apache Tomcat이 질식


16

EC2에서 호스팅되는 Tomcat 앞에 Apache 웹 서버가 있으며 인스턴스 유형은 34GB 메모리로 매우 큽니다.

우리의 응용 프로그램은 많은 외부 웹 서비스를 다루며 피크 시간 동안 요청에 응답하는 데 거의 300 초가 걸리는 매우 거친 외부 웹 서비스가 있습니다.

사용량이 많은 시간 동안 서버는 약 300 개의 httpd 프로세스에서 질식합니다. ps -ef | grep httpd | 화장실 -l = 300

나는 googled하고 수많은 제안을 찾았지만 아무것도 효과가없는 것 같습니다. 다음은 온라인 리소스에서 직접 가져온 일부 구성입니다.

아파치와 바람둥이에서 최대 연결 및 최대 클라이언트의 제한을 늘 렸습니다. 구성 세부 사항은 다음과 같습니다.

// 아파치

   <IfModule prefork.c>
    StartServers 100
    MinSpareServers 10
    MaxSpareServers 10
    ServerLimit 50000
    MaxClients 50000
    MaxRequestsPerChild 2000
    </IfModule>

//수코양이

    <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           connectionTimeout="600000"
           redirectPort="8443"
           enableLookups="false" maxThreads="1500"
           compressableMimeType="text/html,text/xml,text/plain,text/css,application/x-javascript,text/vnd.wap.wml,text/vnd.wap.wmlscript,application/xhtml+xml,application/xml-dtd,application/xslt+xml"
           compression="on"/>

//Sysctl.conf

 net.ipv4.tcp_tw_reuse=1
 net.ipv4.tcp_tw_recycle=1
 fs.file-max = 5049800
 vm.min_free_kbytes = 204800
 vm.page-cluster = 20
 vm.swappiness = 90
 net.ipv4.tcp_rfc1337=1
 net.ipv4.tcp_max_orphans = 65536
 net.ipv4.ip_local_port_range = 5000 65000
 net.core.somaxconn = 1024

나는 수많은 제안을 시도했지만 헛되이 .. 이것을 고치는 방법? m2xlarge 서버가 300 개 이상의 요청을 처리해야한다고 확신합니다. 구성에 문제가있을 수 있습니다.

서버는 사용량이 많은 시간 동안과 [300 초 지연된] 웹 서비스가 응답하기를 기다리는 300 개의 동시 요청이있을 때만 질식합니다.

방금 netstat로 TCP 연결을 모니터링하고있었습니다.

TIME_WAIT 상태에서 약 1000 개의 연결을 찾았습니다. 성능 측면에서 무슨 의미인지 알지 못합니다. 문제에 추가해야한다고 확신합니다.

TOP 출력

 8902  root      25   0 19.6g 3.0g  12m S  3.3  8.8  13:35.77 java
 24907 membase   25   0  753m 634m 2528 S  2.7  1.8 285:18.88 beam.smp
 24999 membase   15   0  266m 121m 3160 S  0.7  0.3  51:30.37 memcached
 27578 apache    15   0  230m 6300 1536 S  0.7  0.0   0:00.03 httpd
 28551 root      15   0 11124 1492  892 R  0.3  0.0   0:00.25 top


 Output of free -m
 total       used       free     shared    buffers    cached
 35007       8470       26536    0          1         61
 8407        26599
 15999       15         15984

 output of iostat
 avg-cpu:  %user   %nice %system %iowait  %steal   %idle
      26.21    0.00    0.48    0.13    0.02   73.15

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda1             14.36         4.77       329.37    9005402  622367592
sdb               0.00         0.00         0.00       1210         48

또한 피크 시간에 membase 서버에 대한 약 10-15k tcp 연결이 있습니다. [local]

MODJK 로그의 일부 오류, 이것이 문제에 약간의 빛을 비추 길 바랍니다 ..

[Wed Jul 11 14:39:10.853 2012] [8365:46912560456400] [error]         ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:18.627 2012] [8322:46912560456400] [error] ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:21.358 2012] [8351:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)
[Wed Jul 11 14:39:22.640 2012] [8348:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)

~

Worker.properties
workers.tomcat_home=/usr/local/tomcat/
worker.list=loadbalancer
worker.tom1.port=8009
worker.tom1.host=localhost
worker.tom1.type=ajp13
worker.tom1.socket_keepalive=True
worker.tom1.connection_pool_timeout=600
worker.tom2.port=8109
worker.tom2.host=localhost
worker.tom2.type=ajp13
worker.tom2.socket_keepalive=True
worker.tom2.connection_pool_timeout=600
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tom1,tom2
worker.loadbalancer.sticky_session=True
worker.tom1.lbfactor=1
worker.tom1.socket_timeout=600
worker.tom2.lbfactor=1
worker.tom2.socket_timeout=600

// 해결

귀중한 제안에 대해 모두 감사하십시오. AJP 1.3 커넥터의 maxThreads 설정을 놓쳤습니다. 이제 모든 것이 제어됩니다.

또한 nginx와 같은 기반 서버도 살펴보기 시작했습니다.


Keepalive 설정은 어떤가요?
Tom O'Connor

페이지를로드하려고 할 때 클라이언트에서 어떤 종류의 오류가 발생합니까?
Shane Madden

1
Apache / httpd 사용자에 대해 허용되는 최대 열린 파일 설명을 늘리셨습니까?
golja

@Tom My Keep Alive 설정은 httpd.conf의 KeepAliveTimeout 10입니다.
john titus

3
이시기에 출력 결과는 top어떻습니까? 어때요 free -m? 그리고 마지막으로 iostat?
Zypher

답변:


13

포트 8009의 AJP 1.3 커넥터에서 maxThreads를 증가 시켰습니까?


(1500)는 내가 예를 바람둥이 당이 무엇인가
존 딛

@ john, 모든 커넥터에 대해 maxThreads = "1500"을 지정 했습니까? AJP 1.3 커넥터 (포트 8009) 용 스탠자를 게시 할 수 있습니까?
HTTP500

이것을 지적 해 주셔서 감사합니다. AJP1.3에 대한 maxThreads 설정이 전혀 없습니다. 이것이 이유 일 수 있습니까?
john titus

1
예, 해당 커넥터의 스탠자에 maxThreads를 추가하십시오. 기본값은 200입니다.
HTTP500

6

Apache 와 같이 nginx또는 lighttpdApache 앞에서 비동기 프록시 웹 서버를 설정하십시오 . Apache는 컨텐츠를 동기식으로 제공하므로 클라이언트가 생성 된 컨텐츠를 전체 다운로드 할 때까지 작업자가 차단됩니다 (자세한 내용은 여기 참조 ). 비동기 (비 차단) 프록시를 설정하면 일반적으로 상황이 크게 개선됩니다 ( nginx프론트 프록시로 사용하여 동시에 실행중인 Apache 작업자 수를 30에서 3-5 로 줄였습니다).


5

어쨌든 당신이 보여준 로그에서 문제가 아파치가 아닌 바람둥이에 있다고 생각합니다. 톰캣에 다시 연결하려는 '오류 110'이 발생하면 톰캣의 리스닝 소켓에 대한 리스닝 백 로그 설정에 더 이상 적합하지 않은 연결 대기열이 있음을 나타냅니다.

From the listen manpage:
   The  backlog  parameter defines the maximum length the queue of pending 
   connections may grow to.  If a connection request arrives with
   the queue full the client may receive an error with an indication
   of ECONNREFUSED or, if the underlying protocol supports  
   retransmission, the request may be ignored so that retries succeed.

추측해야한다면, 서버가 "choking"상태 일 때 HTTP 요청의 대부분이 바람둥이에서 돌아올 때까지 대기하는 것으로 의심됩니다. Tomcat에 프록시되지 않고 아파치가 직접 제공하는 정적 콘텐츠를 가져 오려고 시도하면 정상적으로 '질식'할 때에도 작동합니다.

불행히도 바람둥이에 익숙하지 않지만 대신 이것의 동시성 설정을 조작하는 방법이 있습니까?

아, 그리고 당신은 또한 외부 네트워크 서비스 먹으 렴하는 연결 수 제한 가능성을 고려해야 할 수도 있습니다 그것을 하고있는 당신에게 당신이 당신의 전면에 일을 얼마나 동시성의 조작 차이가 없습니다, 그래서 300 아래로 실제로 모든 연결은 외부 웹 서비스 응답에 의존합니다.

귀하의 의견 중 하나에서 2 분 후에 데이터가 오래되었다고 언급했습니다. 외부 웹 서비스로의 동시 연결 수를 줄이기 위해이 서비스에서받은 응답을 2 분 동안 캐싱하는 것이 좋습니다.


2

이 문제를 해결하는 첫 번째 단계는 Apache의 mod_status를 활성화 하고 보고서를 연구하는 것입니다. 의로운 일이 아닙니다. ;-)

두 번째로 언급해야 할 것은 (나는 스스로 묻지 않은 질문에 대한 답변을 듣는 것을 싫어하지만 ...)은보다 효율적이고 특별한 프론트 엔드 서버를 사용하고 nginx있습니다.

또한, 정확히 한 restart아파치, 아니면 그냥 graceful사라져 다시로드 를? :)


아파치가 다시 시작되었습니다 .. 우아한 재 장전
john titus

어쨌든 @johntitus mod_status는 친구입니다. :)
poige

1

엔터프라이즈 급 배포의 경우 프리 포크 MPM은 사용자가 선택할 수있는 최악의 선택입니다. 이는 아무도 비즈니스와 같은 리소스를 고갈 시키며 스레드를 다시 시작하면 다른 MPM에 비해 영구적입니다.

최소한 기본 이벤트 MPM 을 사용하여 작업자 MPM (apache 2.2 이상)으로 전환 하거나 현재 안정적인 버전 2.4.2로 업그레이드하십시오 .

두 가지 모두 오버 헤드가 거의없이 수천 개의 동시 연결을 쉽게 처리합니다.


고마워요 TIME_WAIT 연결이 계속 증가하고 있습니다. 서버가 350 개 연결에서 응답하지
않음

1
나는 이것이 최악의 선택이라는 것에 동의하지 않습니다-이 맥락에서는 좋지 않은 선택이며 스레드 서버를 사용하면 문제가 완화 될 가능성이 있지만 더 나은 해결책은 이벤트 기반 서버 (nginx 또는 lighttpd)를 사용하는 것입니다. 이벤트 기반 Apache는 엔터프라이즈 배치 IMHO에서 고려할만큼 충분히 성숙하지 않습니다.
symcbean

1

나는 그것이 오래된 이야기라는 것을 알고 있지만 나는 두 가지 언급이 있습니다.

ServerLimit 지시문 에는 하드 코딩 된 제한 이 있습니다. http://httpd.apache.org/docs/2.2/mod/mpm_common.html#serverlimit 최대 20000 / 200K임을 알 수 있습니다.

서버로 컴파일 된 ServerLimit 20000의 하드 제한이 있습니다 (prefork MPM 200000의 경우). 이것은 오타로 인한 불쾌한 영향을 피하기위한 것입니다.

분명히 nodybo는 2를 1로 설정하는 것은 매우 나쁜 생각 이라고 언급했습니다 .

net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1

대기 시간을 일찍 재사용한다는 것을 의미합니다. 로드가 많은 서버가 잘못된 클라이언트와 통신 할 수 있습니다.

나는 그것을 설명하는 아주 좋은 기사를 찾았지만-그것은 프랑스어입니다 ;-) http://vincent.bernat.im/fr/blog/2014-tcp-time-wait-state-linux.html


0

34GB 메모리로 매우 큽니다.

큰 아이언은 병목 현상을 옮기는 웹 서비스를 확장하는 방법이 아닙니다. 그러나이 많은 메모리로도 50000 연결이 특히 다음과 같은 경우 시스템의 기능을 추진하고 있다고 생각합니다.

사용량이 많은 시간 동안 서버는 약 300 개의 httpd 프로세스에서 질식합니다.

"서버 초크"라는 의미로 설명하면 도움이됩니다.

연결에 대한 이러한 높은 제한을 가지지 만 히스테리시스 (최소 / 최대 예비 서버)에 대한 매우 낮은 제한을 갖는 것도 매우 이상합니다.

제공 한 오류 추출에 '열린 파일이 너무 많습니다'라는 내용이 표시되지 않지만 열린 파일 설명자 수와 ulimit 설정을 살펴보면서 시작합니다.


서버는 정상적인 HTML 파일조차도 응답하지 않습니다.
john titus

maxClients를 지금 3000으로 변경했습니다. 여전히 같은 문제
john titus

0

아마도 Apache 사용자가 허용 된 파일 핸들이 부족합니까? 당신은 당신의 게시물에 전혀 언급하지 않았습니다. 현재 Apache가 보유한 파일 핸들 수는 몇 개입니까?


128192 파일 핸들
john

0

이것은 의견과 비슷하지만 평판이 좋지 않기 때문에 말할 수 없습니다. @john titus와 정확히 비슷한 문제가 발생했습니다.

MaxThreads이 문제를 해결하기 위해 AJP 커넥터 를 Apache 스레드 제한에 가깝게 만들었 습니다.

이를 모니터링하기 위해 AJP 포트에서 netstat 명령으로 SYN_SENT netstat 포트 상태 도움말 을 찾았습니다 .

netstat -an | grep :8102 | grep SYN_SENT | wc -l

이것은 0으로 내려 갔으며 AJP 커넥터에 설정된 MaxThread 제한보다 항상 큰 숫자였습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.