Apache & Tomcat trouble shooting (2)
ch02
2. 시스템 지연 발생 주요 모니터링 고려사항 3. 쓰레드 덤프란 4. Jmeter를 활용한 기본 성능 테스트 5. lib 주의사항 6. 장애분석 실무 사례 Jmeter를 활용한 기본 성능 테스트 : 부하량 관련 / 부하가 있을 경우 web was 현상 누적된 처리량, 현재 처리량 (예상 시나리오를 가지고 부하를 던진 후 퍼포먼스 파악) |
1. 시스템 지연 발생 주요 모니터링 방법
1) 장비를 나눠서 서버 검정 → 각각의 부하량에 대해서 얼만큼 부하량을 감당하는지, 튜닝 포인트 판단 가능(물리적 리소스 단위 나눌 필요가 있음)
2) Jmeter로 여러대의 서버에서 네트워크 traffic을 유발시켜서 부하를 줌 (그래서 어디서 병목 현상이 일어나는지 알 수 있음)
2. 시스템 지연 발생 주요 모니터링 고려사항
1) db low query 가 최종 client한테 도달하는 시간까지 고려해야함
- db안에서 3초까지 튜닝해도 client 도달 시간이 아님
2) nginx 의 상태 log와, 에러가지고 전체 판단하면 안됨
3) 설정값으로 인해 병목현상이 발생할 수 있음
ex. db에서 active session이 몇 개인지와 같이
( * session : db 와 연결돼있는 was connection, 실제로 붙은 db 개수, 실제 돌아가면 active section, 안돌아갈 경우 idle이라 부름 / network - network연결 상태(connection) / middleware - 몇명의 사용자가 들어왔는지 )
4) tomcat의 외부시스템 붙은 것과 내부 자바를 확인하려면 pid를 쫓아 가야만 함
5) os 상태 유입량 확인해야 함
tcp 0 0 10.217.69.71:8280 0.0.0.0:* LISTEN 12451/java tcp 0 0 127.0.0.1:10190 0.0.0.0:* LISTEN 12451/java tcp 0 0 10.217.69.71:8209 0.0.0.0:* LISTEN 12451/java TcpState 정의 CLOSED : tcp 연결이 닫혀있다 CLOSE_WAIT : TCP연결의 로컬 엔드포인트에서 로컬 사용자로부터의 연결 종료 요청을 기다리고 있다 CLOSING : TCP연결의 로컬 엔드포인트에서 이전에 보낸 연결 종료 요청의 승인을 기다리고 있다 ESTABLISHED : TCP hand-shake가 완료됨. 연결이 설정되었으므로 데이터를 보낼 수 있음 LISTEN : TCP 연결의 로켈 엔드포인트에서 원격 엔드포인트로부터 연결 요청을 수신하고 있음 TIME_WAIT : TCP연결의 로컬 엔드포인트에서 원격 엔드포인트가 연결 종료 요청의 승인을 받았는지 확인하는데 충분한 시간이 경과하기를 기다리고 있음 → 로컬 끝점은 원격 끝점이 승인을 수신했는지 확인하기 위해 CLOSED로 이동하기 전에 최대 세그먼트 수명(MSL)의 두배를 기다립니다. 내부시스템으로 확인해야함 2. 프로그램과 연결(연동)돼 있는 타 시스템/ 서버에 대해 확인하고 시작 tomcat : netstat -nap | grep 8009 | grep java apache - established 상태가 길지 않음(클라이언트 쪽이라) 현재 유입량 보기엔 작은 수치 |
3. 쓰레드 덤프란
tomcat은 자바가 올라갈 때 각각의 class들의 Thread가 일하고 있는 것들이 block 단위
( * thread : 경량 프로세스. 하나의 프레세스 내에서 여러 개의 실행 흐름(단일, 동시적, 병렬적)을 두어 작업을 효율적으로 처리하기 위한 모델 )
실제로 서비스 단위로 일하는 쓰레드는 유입량이 늘어남 → max user processes 내부 쓰레드 확 늘어나면서 차게 되면 더 이상 쓰레드 못쓰게 됨 <병목 발생>
“지금 상태를 사진으로 찍는다”
echo "Thread dump collecting start..." export DATE=`date +%Y%m%d%H%M%S` echo "1st thread dump : "$DATE>>$ofile 2>&1 echo "<details> <summary> thread dump1 </summary><p>" >>$ofile 2>&1 ## jstack : thread dump comm jstack -l $1 > ./$DATE2/thread_dump1_$1.log cat ./$DATE2/thread_dump1_$1.log>>$ofile 2>&1 sleep 2 echo "</p></details>" >>$ofile 2>&1 export DATE=`date +%Y%m%d%H%M%S` echo "2nd thread dump : "$DATE>>$ofile 2>&1 echo "<details> <summary> thread dump2 </summary><p>" >>$ofile 2>&1 jstack -l $1 > ./$DATE2/thread_dump2_$1.log cat ./$DATE2/thread_dump2_$1.log >>$ofile 2>&1 sleep 2 echo "</p></details>" >>$ofile 2>&1 export DATE=`date +%Y%m%d%H%M%S` echo "3rd thread dump: "$DATE>>$ofile 2>&1 echo "<details> <summary> thread dump3 </summary><p>" >>$ofile 2>&1 jstack -l $PID > ./$DATE2/thread_dump3_$1.log cat ./$DATE2/thread_dump3_$PID.log >>$ofile 2>&1 #jstack -l $PID >>$ofile 2>&1 echo "</p></details>" >>$ofile 2>&1 echo "</PRE></TD></TR>">>$ofile 2>&1 echo "Thread dump collecting complete" |
(실제 덤프 떴던 스크립트)
덤프를 한 번만 찍는 것이 아닌, sleep2 (2초)간격을 두고 약 3번 이상 뜨는 것이 중요함
⇒ thread dump는 획등 당시의 thread 상태만 알 수 있기 때문. 2초간격을 두고 dump를 뜨게 될 경우 이슈 추론이 가능해짐
⇒ os도 이런 모니터링이 필요함 → 실질적인 서비스의 병목, 지연, holding의 원인이 됨
네트워크 상태, os 플랫폼도 고민해봐야 함
apache 유입(io) → 한 파일에 줄 세워서 쏨
tomcat 유입(io) → 일정 데이터 sweep하고 write 시킴
4. Jmeter 시나리오
(1번째 사진) (2번째 사진) 부하량 증가 → tps더 이상 증가하지 않고 유지 = tps처리 못한다는 의미 → 시스템측면에선 병목이 생기는 현상 |
지연 구간 안보임⇒ Normal 문제 발생 시나리오 추가 ⇒ testsleep , sleep_jsp |
#1초동안 찍은 쓰레드 덤프 tid가 같은 경우
⇒ 몇 개의 쓰레드 덤프를 나열해두고 흐름을 보면서 지연 원인 파악 (자바 베이스)쓰레드 덤프 jsp 컴파일 된 위치가 가서 지연유발하는 코드 확인 loop처리 : 1번째사진은 110, 2번째사진은 120같이 holding : db, network경우 홀딩 걸리는 경우도 있음 |
** 인프라 문제 해결 포인트 : 어디를 좁혀서 어디를 봐야할 지 ( ex.1초 이상인 것만 추려서 현상 확인 )
cpu가 튄다? → 메모리 상태 먼저 확인. “Jstat”jstack 0l PID >> test.thread2.logjstat -gcutil PID 2000
** 메모리 덤프 시, 서비스 자체가 홀딩되기때문에 함부로 덤프 뜨면 안됨
- tomcat, jvm 확인할수 있는 row data → thread dump
** 서버 자체의 memory , disk, 충분한 용량 필요 →
현재 instance 의 용량 * 3 +3 있어야 함 ⇒ 그래야 OOM를 확인할 수 있는 덤프 로그 확보 가능
** 기본설정과 ap설정 구분하여 쓸 것 (간혹 혼동하여 같이 쓰는 경우가 있음)
5. lib 주의 사항
tomcat lib 엔진 기본 외 라이브러리에 올리면 안되는 이유 : ap있는 라이브러리와 엔진 라이브러리 버전이 틀리면 무엇이 먼저 로딩될 지 장담할 수 없다. 사용해야 참조해서 올라옴. 엔진 단에 추가 라이브러리 금지. 엔진에있는 것 참조하게 됨.(wildfly도 마찬가지) /tomcat/apache-tomcat-8.5.53/lib /tomcat/domains/tc85_01/lib /tomcat/application/tc85_01/simplehome/WEB_INF/lib → 만일 내부 중복 라이브러리가 존재할 경우, 내부 클래스 엉키는 경우 발생 라이브러리 맞춰야 함 |
6. 장애 분석 실무 사례
db병목 발생 사례 | # db병목 발생 사례 단 건 쿼리가 아니라 대량 건의 쿼리가 들어올 때 발생하는 병목현상은 단 건 쿼리 튜닝은 해결 x <대량 부하와 단건 쿼리 부하는 다름> 교육 사이트 메인 화면에 자잘하게 db불러오는 경우 → 디비까지 안가고 캐시화하여 해결 db connection 부족할 경우 ) db connection늘린다? 오히려 connection 개수 줄이고나서 퍼포먼스 부분을 잡아야함(5개 connection, 10개 connection, 20개 connection)
was 주요 기능 중 하나 : db보호 (client → (os(web)) → (os(was(application))) → DBMS) ⇒ db가 몇개까지 수용할 수 있는지/ was - 몇개를 해야 db퍼포먼스를 유지할 수 있는지 |
디비 공유 사례 | # 디비 공유 사례 - 아이폰 예판 8(일반고객) : 2(대리점) 대리점 막아버림(일반고객db터질 수 있으므로) 전체 시스템과 시나리오 고려해야만함, 대리점 증량x 오히려 악화 전체를 보고 협의나 포기를 해야했던 상황 db는 중요함, 무너지면 안됨 |
web server 과부하 → was 영향 사례 | # 복합 현상 발생 “web server 과부하가 was에 영향을 끼치는 사례 web was가 같은 서버에 있을 경우, was메모리 부족으로 인해 web 서버 resource부족하는 경우도 있었음 ⇒ web was 서버 합쳐지지 않게끔, 솔루션 별도로, 메모리에 대한 확보 메모리 고려할 것 ⇒ 서버 전체에 대한 resource 상태 점검 필요 |
ap에서 들고는 있는데 쿼리는 안던지고 connection만 열어두었던 사례 |
# ap에서 들고는 있는데 쿼리는 안던지고 connection만 열어두었던 상황 - transaction길게 갖고있는 경우 ap에서 db 쓰고 return안 된 경우 “ActiveCount” ⇒ 쿼리와 쿼리사이 갭차이가 많았음 (1) AP → DB ← (2) (1)과 (2) 쿼리 사이 간격이 점점 늘어남 이유 : db관련된 처리를 log로 남기고, result도 log로 남김 로그 처리는 직렬로 돼 있어서 줄이 생김 ⇒ 결국 아웃풋(traffic) 자체가 늦어짐 /idle section 많아보임 ⇒ log자체를 들어냄 Sync 방식의 로그 처리로 병목으로(logback → log4j v2) 변경 후 async 방식으로 일부 추가 result object 로그 출력 부분정리 (connection 증가의 원인) (client → (os(web)) → (os(was(application))) → DBMS) →외부시스템 Fact기반에 문제 가능성 고려 (AP와 논의 ) Gclog - pool gc가 잦은 떨어지는 시점이 문제 ⇒ 누적 but 단 건이 아니기에 AP clear정리되는 것을 찾아줘야함 lwp / thread dump 뽑아서 비교 |
cpu 과다 사용 이슈 사례 | # 2023.02 cpu 과다 사용 이슈 object가 null이 아닌 경우 → object 지속적으로 생성 ⇒ 무한루프에 빠지면 cpu 잡아 먹으면서 내부 object 누적 ⇒ cpu도 튀고 메모리도 부족 <흐름인지 중요- cpu가 무엇이 다른지 등 > |
*문제를 추려가는 식으로 좁혀가는 것이 중요*