달력

12025  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

AIX - was의 병목현상

WAS 2008. 6. 4. 19:48

1. 올리신 건 중 SIGSEGV의 유형을 보면 sun.io.ByteToCharDoubleByte.convert()에서
  sun.io.ConversionBufferFullException이 발생했습니다.
  극히 정상적인 이 메소드에서 유일하게 ConversionBufferFullException이 발생할 수
  있는 경우는 메모리가 부족할 때 일 것입니다.
  왜 메모리가 부족할 까요? 잘 돌땐 잘 도는 때, 왜 에러가 생길까요?
  가장 가능성 있는 부분은 어디신가 메모리 누수가 있기 때문일 것입니다.
  엔진의 Bug일 수도 있고, ResultSet/Statement를 close()하지 않아서일 수도 있고,
  어떤 응용어플리케이션이 GC의 대상이 되지 않는 구조의 메모리 점유를 할 수도
  있고, 가능성은 매우 다양합니다.
  아래와 유사한 기능으로 주기적으로 Free 메모리크기를 확인해 보세요

[mem.jsp]
--------------------8><---------------------------------------------------
<%@ page session="false" contentType="text/html" %>
<html><body>
<b><%= java.net.InetAddress.getLocalHost().getHostAddress() %></b>
<%= new java.util.Date() %><br><br>

<%
   Runtime rt = Runtime.getRuntime();
   long free = rt.freeMemory();
   long total = rt.totalMemory();
   out.println("Free  = <b>"+(free/1024/1024) +"</b> MB ("+free +" bytes)<br>");
   out.println("Total = <b>"+(total/1024/1024)+"</b> MB ("+total+" bytes)<br>");
%>
</body></html>
--------------------8><---------------------------------------------------

[gc.jsp]
--------------------8><--------------------------------------------------
<%@ page session="false" contentType="text/html" %>
<html><body>
<h1>WebSphere Memory Monitor(GC Version)</h1>
<%= new java.util.Date() %><br>

<%
   System.out.println(java.net.InetAddress.getLocalHost().getHostAddress()+"<br>");
   Runtime rt = Runtime.getRuntime();
   long free = rt.freeMemory();
   long total = rt.totalMemory();
   out.println("Free  = " + (free/1024/1024) + " MB (" + free + " bytes)<br>");
   out.println("Total = " + (total/1024/1024) + " MB (" + total + " bytes)<br>");
   out.println("----------------------------------------------------<br>");
   System.gc();
   rt = Runtime.getRuntime();
   free = rt.freeMemory();
   total = rt.totalMemory();
   out.println("Free  = " + (free/1024/1024) + " MB (" + free + " bytes)<br>");
   out.println("Total = " + (total/1024/1024) + " MB (" + total + " bytes)<br>");
%>
</body></html>
--------------------8><---------------------------------------------------

 어떤 곳에서 메모리 누수가 있는 지는 profiling 도구나, 혹은 다른 방법을 찾아보셔야
 할 것입니다.

2.
2.1  DB Lock 일 가능성이 있습니다. Oracle 쪽에서 확인해 보세요.

2.2 만약 그렇지 않다면, 응답이 느려질 때, 의도적으로 kill -4 <pid>, kill -3 <pid> 로
  발생시킨 javacore에서 대부분이 Statement executeQuery() 후 데이타를 기다리고 있는
  것은 극히 정상적인 상태로 보여집니다.  RS6000 B80(2-way,1GB)사양에서 Oracle과
  WebLogic을 함께 사용하고 있는데, 어쩌면 해당 SQL 쿼리 및 전체적인 성능이 낮기
  때문일 것입니다.
  topas나 vmstat로 시스템을 확인해 보세요. vmstat 의 fr,sr값들이 지속적으로 0
  이외의 수치로 나타난다거나, CPU가 100%라든가...
  oracle 프로세스가 대부분의 메모리와 CPU를 점유할 것이라는 추정은 별도 틀리지
  않을 것입니다. 이 경우라면 DB서버와 WAS서버를 분리할 시기가 온 듯 하군요.
 
  혹은 메모리나 CPU 의 bottle-neck이 아닐지라도, 웹스트레스테스트툴을 이용하여
  몇몇 주목되는 응용어플리케이션의 단위시간당 최대 처리가능건수를 구해 보세요.
  그 이상으로 호출이 발생하면, 그같이 응답이 느려지고 hang현상에 빠지는 것은
  기술적으로만 보면 당연한 현상인 것이지요.

PS: 자바서비스넷에 있는 글들이 도움이 될 것입니다. 비록 많은 부분에서
 WebSphere기반으로 설명되어 있지만, 동일하게 여타의 웹어플리케이션서버에서도
 적용가능하며, 문제을 찾아가는 방법론 상의 문제일 뿐입니다. 각종 글을 이용하여
 아래 사항을 항상 모니터링 하세요

(1) vmstat 의 fr,sr 값의 변화(특히 지속적으로 0 이외의 값이 나타나면 메모리부족)

(2) vmstat 의 CPU상황(90-100%가 지속적이라면 CPU부족)

(3) httpd 데몬의 개수변화
    ps -ef|grep httpd| wc -l

(4) 80 port로 ESTABLISH 된 개수 변화
    netstat -n | grep tcp4 | grep EST | \
      nawk '{ if ( index($4,"<server_ip_addres>.80")>0) {print $0;}}' | wc -l

(5) 사용자 PC로 날아가는 N/W 병목

    5-1) topas 로 보았을 때, 특정 N/W으로(en0라 가정) 전송되는 KB 수
    예를 들어 10Mbps 라인이라면 대략 700-900 KB/sec 가 최대

    NOTE: 실 전송속도는 일반적으로 라인 최대치의 60% 로 봄
    T1: 1.544 Mbps -----> 1.544 * 1024 / 8 * 0.6   = 118 KB/sec
    E1 : 2.048 Mbps ----> 2.048 * 1024 / 8 * 0.6   = 157 KB/sec
    10 Mbps  -----------> 10 * 1024 / 8 * 0.6      = 768 KB/sec
    T3 : 43.7361 Mbps --> 43.7361 * 1024 / 8 * 0.6 = 3359 KB/sec
    100Mbps ------------> 100  * 1024 / 8 * 0.6    = 7680 KB/sec

    5-2)
    혹은  80 port의 out-bound send queue에 지속적으로 쌓이는 현상이 일어나는지
    여부 확인

    netstat -n | grep tcp4 | grep EST | \
      nawk 'BEGIN{s=0;}
            { if ( index($4,"<server_ip_addres>.80")>0) { s+=$3; }} \
            END{ printf("%d", s/1024); }'

    이 수치는 80 port에서 고객의 PC로 날아가는 TCP/IP 네트웍 레벨에서 send Q에
    쌓이는지를 보는 것으로서, 이 수치가 지속적으로 0 이외의 수치, 혹은 지속적으로
    100 KB이상을 넘어서면 N/W bottle-neck을 의심해 볼 수 있음.


(6) 웹서버와 WebLogic과의 소켓연결개수(가정 7001이라 가정했을 때)
    netstat -n | grep tcp4 | grep EST | \
      nawk '{ if ( index($4,"<server_ip_addres>.7001")>0) {print $0;}}' | wc -l

    혹은 lsof 라는 유틸리티를 설치하여

    was_pid=`ps -ef|grep java|grep ....WebLogic process ....| awk '{print $2}'
    lsof -p $was_pid | grep 7001 | grep EST | wc -l

    현재, 질문하신 분의 경우, WebLogic의 동시 최대 처리가능한 ExecuteThread 수는
    30개로 설정되어 있습니다. 만약, 스트레스테스트 환경이 아니라, 실 운영시에
    위 수치가 지속적으로 증가하여 30에 육박한다면 이는 hang현상을 의미하게 됩니다
    아래의 7)글을 참조하세요. 그리고, 자바서비스넷의 각종 문서에서 언급한 PPC라는
    용어를 찾아 보세요.

 (7) DB연결개수 변화(Oracle JDBC Thin: 1521 port라 가정했을 때)

    lsof -p $was_pid | grep 1521 | grep EST | wc -l

    이 수치가 DB Pool에서 설정해 둔 max 20 에 도달한다면 일단 장애가 일어나는
    것은 당연한데, 그렇다고 max 20 을 100 이나 200 으로 변경해 주는 행위는
    성능진단경험이 부족한 엔지니어가 흔히 범할 수 있는 오류중의 하나입니다.
   
    max 수치를 설정하는 가이드는 장애가 없으면서 극히 잘 서비스한 시간대에 최대로
    올라간 DB연결개수를 max로 설정하시면 됩니다.(사이트마다 다르겠지요)
   
    어떤 성능상의 이슈로 인해, 처리능력과 호출빈도의 상관관계에서 밀리기 시작하면
    DB연결개수가 증가하는 것은 일시적인 현상이 아니라 지속적인 현상으로 나타납니다.
    결국, 20이든 50인든 200 이든 "50보 100보"인 것이지요

    근본적으로 SQL를 튜닝하는 것과 같이 해당 응용어플리케이션의 성능을 높여 주어야
    합니다.

    NOTE: OCI방식이라면 잡아낼 방법이 없음...

    NOTE: 앞의 (2),(3),(4),(5),(6),(7) 정보를 로깅하는 shell script의 샘플은 아래의
    문서를 참조세요.
    99   RE: netstat & lsof 
    http://www.javaservice.net/~java/bbs/read.cgi?m=appserver&b=engine&c=r_p&n=1007110331
   

(8) 현재 실행중이 서블렛/JSP의 개수 모니터링
    requestmon 적용.

    현재실행중인 서비스 모니터링 - requestmon -
    http://www.javaservice.net/~java/bbs/read.cgi?m=appserver&b=was&c=r_p&n=982131370
    Orion 서버에 requestmon 적용하기
    http://www.javaservice.net/~java/bbs/read.cgi?m=appserver&b=orion&c=r_p&n=1009556331
    Resin2.0.4 서버에 requestmon 적용하기
    http://www.javaservice.net/~java/bbs/read.cgi?m=appserver&b=engine&c=r_p&n=1009768606


(9) 응답이 3초 이상걸린 URI 기록
    requestmon 적용

(10) 메모리 heap 변화 모니터링
    앞서의 mem.jsp, gc.jsp 참조...

(11) AIX 플렛폼의 IBM JDK 에 한하여, 현재 장애를 유발하고 있는 시점에서, 어차피
    내렸다 올려야 하는 상황이라면, 아래와 같이 현재 돌고 있는 내부의 Thread Dump를
    받는 행위는 현재의 상황을 이해하는데 매우 필수적입니다.

   1) dbxtrace.sh

     a) 현재 프로세스가 죽지 않은 상황일 때,
        # dbxtrace.sh -a <was_pid> > dbxtrace.txt

     b) "core" 파일이 방금 막 생겼을 때,
        # mv core core2
        # dbxtrace.sh -c core2 > dbxtrace.txt

    NOTE: dbxtrace.sh 에서 정확한 정보를 보려면 시스템의 fullcore 옵션이 true이어야
    합니다.

    #Please check using "lsattr -El sys0 | grep fullcore" if fullcore is   
    #"true". if not, do a "chdev -a fullcore=true -l sys0".
    #For core files:
    #    Usage:   dbxtrace.sh [executable] [core]
    #      or :   dbxtrace.sh -c corefile > dbxtrace.txt
    #    (Please make sure you use the java executable and not the java script)
    #
    #To attach to a running or hung process
    #    Usage:   dbxtrace.sh -a PID >  dbxtrace.txt
    #    Example: dbxtrace.sh -a 1234 > dbxtrace.txt

    dbxtrace.sh
    AIX Java App. SIGSEGV 진단 방법에 관한 예
    http://www.javaservice.net/~java/bbs/read.cgi?m=appserver&b=was&c=r_p&n=1000371692


   2) javacore??????.txt 의도적으로 만들기

    # kill -3 <was_pid>

    javacore 파일에는 현재 수행중의 ExecuterThread 가 무엇을 하고 있는지 확인할 수
    있습니다. ( javacore????.txt 는 IBM JDK 에 한해서 발생합니다. SUN JDK에서는
    발생하지 않습니다.)
    (javacore의 라인이 255글자를 넘어가기 때문에 vi 로는 열지 못하니 more 로 보세요)
   


NOTE:
 아직 아래 글을 읽지 않았다면, 꼭 읽어 보세요.
 [강좌]웹기반시스템하에서의 성능에 대한 이론적 고찰
 http://www.javaservice.net/~java/bbs/read.cgi?m=resource&b=consult&c=r_p&n=1008701211


================================================
  자바서비스넷 이원영
  E-mail: javaservice@hanmail.net
  PCS:011-898-7904
================================================

'WAS' 카테고리의 다른 글

jeus 4.0 - DATA-SOURCE 패스워드 암호화  (0) 2008.06.04
톰캣의 maxThreads, DBCP 장애  (0) 2006.02.24
Apache 가상호스트 설정  (0) 2006.02.21
tomcat4 가상호스트 설정  (0) 2006.02.21
Posted by 알 수 없는 사용자
|