티스토리 뷰
본 포스팅에서는 Linux에서의 CPU 과점유현상을 분석해보겠습니다.
먼저 CPU 사용률은 서버의 중요한 성능포인트가 됩니다. CPU사용률이 지나치게 높을경우, Web/WAS 뿐만아니라 H/W, Network등의 bottleneck(병목)현상을 유발하게됩니다. 이번 포스팅에서는 Linux에서의 CPU과점유현상에 대해 알아봅니다.
먼저, 특정 계정의 CPU 사용률을 보기위한 명령어는 다음과 같습니다. 자세한 옵션은 아래에서 살펴보겠습니다.
top -H -U [계정명]
[wildfly@kmkang~/jboss64/bin$]top -H -U wildfly
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 4560 wildfly 20 0 7155556 587304 21260 R 99.9 7.4 26:49.26 java |
* 필드
PID : 프로세스 ID (PID)
USER : 프로세스를 실행시킨 사용자 ID
PRI : 프로세스의 우선순위 (priority)
NI : NICE 값. 일의 nice value값이다. 마이너스를 가지는 nice value는 우선순위가 높음.
VIRT : 가상 메모리의 사용량(SWAP+RES)
RES : 현재 페이지가 상주하고 있는 크기(Resident Size)
SHR : 분할된 페이지, 프로세스에 의해 사용된 메모리를 나눈 메모리의 총합.
S : 프로세스의 상태 [ S(sleeping), R(running), W(swapped out process), Z(zombies) ]
%CPU : 프로세스가 사용하는 CPU의 사용율
%MEM : 프로세스가 사용하는 메모리의 사용율
COMMAND : 실행된 명령어
* 옵션
-a : 메모리 사용에 따라 정렬
-b : 배치 모드에서 시작
-c : 명령어 대신 명령어 라인을 보여줌
-d : 업데이트 간격을 조정
-h : 도움말
-H : 모든 개별 쓰레드가 보여짐
-i : 좀비(zombie) 또는 Idle 상태의 것들은 무시됨
-m : VIRT 대신 USED를 보고
-M : 메모리 유닛(K/M/G)을 보여줌
-n : 반복의 최대 수를 지정
-P : 지정된 프로세스 ID들만 보여줌
-s : 보안 모드로 시작
-S : 누적 시간 모드로 시작. 활성화되면 각 프로세스는 CPU를 사용한 시간과 함께 출력
-u : 지정된 유효 사용자에 의한 프로세스만 보여줌
-U : 지정된 사용자에 의한 프로세스만 보여줌. 사용자는 실제, 유효한, 저장된 및 파일시스템 UID를 의미
-v : 프로그램 라이브러리 버전을 출력
* top 실행 중 명령어
* 스페이스바 : 화면 갱신
* k : kill 명령
* r : nice 값 변경
(nice는 우선순위를 뜻하며, -20 ~ 20 까지 사용가능. 낮을수록 우선권이 높음. 기본값은 0)
* Z : 화면 출력 색상 변경
(a 또는 w를 누르면 색상이 순차적으로 변경되며 보여줌)
* z : Z로 변경된 출력 색상과 기본 출력 색상간 전환
* B : 글자 두껍게
* l : top 출력 상단의 load avg 항목 on/off
* t : top 출력 상단의 프로세스와 cpu 항목 on/off
* m : top 출력 상단의 메모리 항목 on/off
* O : 화면 정렬(sort) 기준 지정
* r : nice 조정 (-20 ~ 20. 우선순위 높음 ~ 낮음)
* q : top 종료
그럼 이제 CPU과점유 현상을 재현해보고, 분석해보도록 하겠습니다.
1.Thread Dump 생성
리눅스환경에서는 일반적으로 아래와 같이 thread dump수집을 할 수 있습니다.
kill -3 JAVA_PID jstack -l JAVA_PID > jstack.out (Open JDK, Sun JDK) |
PID를 확인하겠습니다.
java process를 확인합니다. 4442로 확인되네요.
[wildfly@kmkang~/PocApp/JBTEST$]ps -ef | grep java wildfly 4442 4322 92 16:40 pts/1 00:02:16 /usr/local/jdk1.8.0_152/bin/java -D[Standalone] -server -XX:+UseCompressedOops -verbose:gc -Xloggc:/home/wildfly/jboss64/standalone/log/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=3M -XX:-TraceClassUnloading -Xms1303m -Xmx1303m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true -Djboss.modules.policy-permissions=true -Dorg.jboss.boot.log.file=/home/wildfly/jboss64/standalone/log/server.log -Dlogging.configuration=file:/home/wildfly/jboss64/standalone/configuration/logging.properties -jar /home/wildfly/jboss64/jboss-modules.jar -mp /home/wildfly/jboss64/modules -jaxpmodule javax.xml.jaxp-provider org.jboss.as.standalone -Djboss.home.dir=/home/wildfly/jboss64 -Djboss.server.base.dir=/home/wildfly/jboss64/standalone -Djboss.server.base.dir=/home/wildfly/jboss64/standalone -Djboss.node.name=standalone -c standalone.xml -b 0.0.0.0 -bmanagement=IP -Djboss.socket.binding.port-offset=50 wildfly 4650 4262 0 16:43 pts/1 00:00:00 grep --color=auto java |
[wildfly@kmkang~/jboss64/$]jstack 4442 > dump.txt
2.top 결과에서의 PID를 HEX 값으로 변환합니다. 아래와 같이 프로그래머 계산기를 사용하시면 됩니다.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 4560 wildfly 20 0 7155556 587304 21260 R 99.9 7.4 26:49.26 java |
3.Thread dump 내에서 HEX값인 11d0을 찾아보겠습니다.
자세히 확인해보면, sleep1.jsp파일이 stack trace중 하나로 확인되네요.
"http-/0.0.0.0:8130-1" #112 daemon prio=5 os_prio=0 tid=0x00007fad5410c800 nid=0x11d0 runnable [0x00007fadae695000] java.lang.Thread.State: RUNNABLE at org.apache.jsp.sleep1_jsp._jspService(sleep1_jsp.java:58) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:69) at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:365) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:309) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:242) at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:231) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149) at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:150) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97) at org.jboss.web.rewrite.RewriteValve.invoke(RewriteValve.java:466) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:559) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:854) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:926) at java.lang.Thread.run(Thread.java:748) |
실제로 sleep1.jsp 내에는 아래와 같은 소스가 존재합니다.
<%@ page contentType="text/html; charset=euc-kr" %> <% int i=0; int sum=0; while (i<=0) { sum=sum+i; i=i++; } %> |
또한 명시적으로 stack trace에서 확인가능한 sleep1_jsp.java 의 58라인에 어떤 소스가 있는지 확인해보겠습니다.
42 try { 43 response.setContentType("text/html; charset=euc-kr"); 44 response.addHeader("X-Powered-By", "JSP/2.2"); 45 pageContext = _jspxFactory.getPageContext(this, request, response, 46 null, true, 8192, true); 47 _jspx_page_context = pageContext; 48 application = pageContext.getServletContext(); 49 config = pageContext.getServletConfig(); 50 session = pageContext.getSession(); 51 out = pageContext.getOut(); 52 _jspx_out = out; 53 54 out.write('\n'); 55 56 int i=0; 57 int sum=0; 58 while (i<=0) { 59 sum=sum+i; 60 i=i++; 61 } |
개발자는 CPU과점유를 일으키는 해당 소스코드에 대한 검토를 해야합니다.
이상으로 리눅스상의 CPU과점유 현상 분석에 대해 알아보았습니다. 다음 포스팅에서는 다른 OS상에서의 CPU과점유 현상을 분석해 보겠습니다.
고맙습니다.
'② 성능 최적화, 트러블 슈팅 > ⓣ TroubleShooting' 카테고리의 다른 글
OS별 Port로 Process 찾는법 (0) | 2019.07.04 |
---|---|
[Memory Analyzer]HeapDump분석시 SUN Hot Spot계열 URL찾기 (1) | 2019.07.04 |
[503] Service Temporarily Unavailable에 대한 고찰 (1) | 2018.08.25 |
[500] Internal Server Error에 대한 고찰 (0) | 2018.08.20 |
[404] Not Found에 대한 고찰 (2) | 2018.08.18 |
- Total
- Today
- Yesterday
- OpenStack
- jeus
- Da
- 마이크로서비스
- JEUS7
- SWA
- JBoss
- node.js
- 마이크로서비스 아키텍처
- nodejs
- apache
- MSA
- Architecture
- webtob
- git
- Docker
- JEUS6
- kubernetes
- TA
- SA
- aws
- openstack token issue
- openstack tenant
- wildfly
- k8s
- API Gateway
- 아키텍처
- 쿠버네티스
- aa
- 오픈스택
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |