티스토리 뷰

728x90
반응형
 

 포스팅은 LINUX 서버의 CPU 과점유 현상 발생 시 대처 방안을 가이드합니다.


성능을 측정하는데는 여러가지 요소가 있습니다.

그중 중요한 CPU는 WEB/WAS 뿐만아니라 H/W, Network등의 병목을 유발하는 주요 성능 포인트 입니다.

그럼 CPU 성능 이슈가 발생했을 때 어떻게 처리해야 할 지 OS별로 알아보도록 하겠습니다
 

본 시간에는 LINUX 서버입니다.

손쉽게 CPU 사용률을 확인할 수 있는 top 명령어를 통해 우선적으로 확인합니다.


1. top



top -U 옵션을 줘서 해당 계정(narason) 정보만 출력하도록 합니다.

Shift + h를 누르면, Thread 정보를 출력합니다.



==> 변경된 정보



해당 정보는 아래와 같이 한번에 출력이 가능합니다.

# top -H -U narason 



위 정보를 살펴 보면, 최상위의 7759 PID를 갖는 자바 Thread가 cpu를 96.9% 점유하고 있는 것을 볼수 있습니다.

2. Thread Dump 생성

먼저 Sun HotSpot 계열 Thread Dump에 대해 간단히 살펴 보고 넘어가도록 하겠습니다.

Thread Dump 생성

- Java process에 signal을 전달하여 생성합니다. (SIGQUIT)
- Java process를 만든 벤더들이 내부적으로 SIGQUIT에 대한 signal을 catch하여 그 시점의 stack trace를 출력하는 것입니다.
- Unix 계열 (Sun, HP-UX, AIX, Linux 등)
# kill -3 [프로세스 ID]


생성 위치
- Sun 계열 (Sun, HP-UX, Linux 등)의 경우는 Thread dump를 수행하면 STOUT으로 출력됩니다. STOUT은 표준 출력을 말합니다. 표준 출력이란 프로세스가 기본적으로 생성되는 입출력 (FD) 중의 하나입니다. (0:STDIN, 1:STDOUT, 2:STDERR)
WAS의 경우 로그파일에 출력되게 됩니다.


# 참조 Thread 상태 정보
[Sun jdk 1.5]

- allocated : Thread가 생성되기 위해 메모리 할당 된 상태
- initialized : Thread가 초기화 된 상태
- runnable : Thread가 java virtual machine 내에서 수행 중인 상태
- waiting for monitor entry : Thread가 Monitor lock을 획득하기 위해 대기중인 상태
 Monitor lock이란 Multi thread 환경에서 thread를 동시 접근하는 것을 막아 database 부하를 줄이거나 thread 병합을 막는 역할을 합니다. 해당 lock은 synchronized 된 object에만 적용 됩니다. 정리하자면, synchronized 된 object를 현재 사용 중인지 아닌지 검사하는 것이 Monitor lock입니다.
- waiting on condition : Thread가 조건 변수(Condition Variable)에 의해 대기 중인 상태
- in object wait() : Thread가 Object.wait()으로 인해 대기 중인 상태
- sleeping : Thread가 I/O등에 의해 대기 중인 SLEEP 상태가 된 경우

[Sun jdk 1.6]

- NEW : Thread가 생성되기 위해 메모리에 할당 된 상태
- RUNNABLE : Thread가 java virtual machine 내에서 수행 중인 상태
- BLOCKED : Thread가 Monitor lock을 획득하기 위해 대기중인 상태
- WAITING : Thread가 특정 작업을 위해 다른 Thread를 무기한 대기하는 상태
- TIMED_WAITING : Thread가 특정 작업을 위해 정해진 시가만큼 다른 Thread를 대기하는 상태
- TERMINATED : Thread가 exited 된 상태


위 내용을 기반으로 Thread Dump를 생성합니다.

LINUX의 경우 WAS Server Log 동일 경로의 jvm.log에 생성됩니다.

$JEUS_LOG_HOME/server1/jvm.log


3. Thread Dump 분석

Thread Dump를 편집기로 오픈 한 후 ThreadDump 생성 시 확인한 PID 7759를 HEX로 변환한 결과 값을 찾습니다.

7759를 변환하면, 0x1E4F이며, 현재 CPU 96%를 잡아 먹는 녀석을 드디어 찾았습니다.



자 그럼 이후에는 어떤 조치를 해야 할 까요?


4. 조치

WAS 엔지니어의 입장에서는 JSP 파일(상단의 Stack 정보를 통해 Compiled 된 jsp 파일을 찾을수 있음 - sleep.jsp)과 Compile java source를 전달하면 완료되지만, 직접 분석을 진행해 보도록 하겠습니다.

JSP 파일과 JAVA 파일을 열어보면 다음과 같습니다.

[sleep.jsp]

<%@ page contentType="text/html; charset=euc-kr" %>
<%
        int i=0;
        int sum=0;
        while (i<=0) {
                        sum=sum+i;
                        i=i++;
        }
%>

이거만 봐도... 문제가 있죠?? while문이 무한루프가 돌게 작성이 되어 있네요..

다만 단순한 소스가 아니고 Thread Dump 스택의 경우 아래와 같이 Compiled java source 기준으로 line(68)이 표시 되기 때문에 실제로는 java Source를 확인해야 합니다.

&quot;http1-13 [server1-487]&quot; daemon prio=10 tid=0x00007fb42400d000 nid=0x1e4f runnable [0x00007fb4687bc000]
   java.lang.Thread.State: RUNNABLE
        at jeus_jspwork._700_sleep_5fjsp._jspService(_700_sleep_5fjsp.java:68)
        at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
        at jeus.servlet.jsp.JspServletWrapper.executeServlet(JspServletWrapper.java:66)
        at jeus.servlet.engine.ServletWrapper.execute(ServletWrapper.java:149)
        at jeus.servlet.jsp.JspServletWrapper.execute(JspServletWrapper.java:40)
        at jeus.servlet.engine.RequestProcessor.run(RequestProcessor.java:211)
        at jeus.util.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:1211)
        at jeus.util.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:1261)
        at jeus.servlet.engine.WebThreadPoolExecutor$WebRequestWorker.run(WebThreadPoolExecutor.java:340)
        at java.lang.Thread.run(Thread.java:722)

 

[_700_sleep_5fjsp.java] 

     51     try {
     52       response.setContentType("text/html; charset=euc-kr");
     53       pageContext = _jspxFactory.getPageContext(this, request, response,
     54                         null, true, 8192, true);
     55       _jspx_page_context = pageContext;
     56       application = pageContext.getServletContext();
     57       config = pageContext.getServletConfig();
     58       session = pageContext.getSession();
     59       out = pageContext.getOut();
     60       _jspx_out = out;
     61
     62       out.write('\n');
     63
     64         int i=0;
     65         int sum=0;
     66         while (i<=0) {
     67                         sum=sum+i;
     68                         i=i++;
     69         }
     70
     71       out.write('\n');
     72     } catch (java.lang.Throwable t) {
     73       if (!(t instanceof javax.servlet.jsp.SkipPageException)){
     74         out = _jspx_out;
     75         if (out != null && out.getBufferSize() != 0)
     76           try {
     77             if (response.isCommitted()) {
     78               out.flush();
     79             } else {
     80               out.clearBuffer();
     81             }
     82           } catch (java.io.IOException e) {}
     83         if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
     84         else throw new ServletException(t);
     85       }
     86     } finally {
     87       _jspxFactory.releasePageContext(_jspx_page_context);
     88     }
     89   }

68 라인에 가봤더니 동일한 위치에서 걸려 있네요.. 해당 부분의 수정이 필요하다는 것을 판단하고 개발자에게 전달하면 1Cycle 완료!


자 다음에는 SunOS 편으로 찾아 오겠습니다.

감사합니다.


# 댓글과 추천은 글쓴이에게 힘이됩니다.!

728x90
반응형

'⑥ 네트워크, 운영체제 > ⓞ OS' 카테고리의 다른 글

[CPU 과점유] HP-UX 편  (0) 2018.07.19
[CPU 과점유] SunOS 편  (0) 2018.07.19
[ETC] OS별 TCP Trace Dump 기록 방법  (0) 2018.06.18
[ETC] OS Hostname Resolution  (0) 2018.06.08
[ETC] RAID Level  (0) 2018.03.25