[JVMSTAT]jvmstat 3.0 설치방법
# java JVM Memory Perf 분석
- Tools : jvmstat-5.zip
J2SE 1.5 이상
- 구성 환경 :
Host A에 설치 동작중인 Java Applicaton( Unix )에 대한 메모리 이용율을
Host B( Windows )에서 Remote로 확인
- Host A 설치내용
J2SE 1.5 이상의 버젼이 설치 되었는지 확인
참고 : Java 1.5부터는 jvmstat의 내용이 일부 포함되어 배포가 됨.
jvmstat를 위한 Home Directory 생성 ( /usr/local/jvmstat )
$ mkdir /usr/local/jvmstat/
RMI Connection 권한 설정 파일 생성
$ cd /usr/local/jvmstat/
$ vi jstatd.all.policy
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
jvmstat를 위한 환경 변경 설정
$ export JAVA_HOME=/usr/local/java
$ export JVMSTAT_HOME=/usr/local/jvmstat
$ export PATH=$JVMSTAT_HOME/bin:$JAVA_HOME/bin:$PATH
jstatd 실행 ( jvmstat 2.0의 perfagent와 같음. )
$ cd /usr/local/jvmstat/
$ cat start.sh
#!/bin/bash
export JVMSTAT_HOME=/usr/local/jvmstat
export JAVA_HOME=/usr/local/jdk1.5.0_02
export PATH=$JAVA_HOME/bin:$JVMSTAT_HOME:$PATH
# RMI Registry Start
$JAVA_HOME/bin/rmiregistry &
# JSTAT PerfAgent Start
nohup \
$JAVA_HOME/bin/jstatd \
-J-Djava.security.policy=$JVMSTAT_HOME/jstatd.all.policy
\
-J-Djava.rmi.server.logCalls=true \
&
$ sh start.sh
local test 수행
$ jps
$ jstat -gcutil 11216 1000 10 ( 11216은 jvmps에서 vmid )
Java RMI Connection을 위한 설정
$ vi /etc/hosts
위 hostname ( backup )을 RMI로 호출될 Interface의 IP로 변경 한다.
127.0.0.1 localhost.localdomain localhost
192.168.1.117 backup
- Host B 설치 내용
J2SE 1.5 이상의 버젼이 설치 되었는지 확인
jvmstat-3.zip를 C:\에 압축 풀기 ( visualgc에 대한 내용만이 포함되어 있음. )
jvmstat를 위한 환경 변경 설정
SET JAVA_HOME="C:\Program Files\Java\jdk1.5.0_02"
SET JVMSTAT_HOME="C:\jvmstat"
SET JVMSTAT_JAVA_HOME="C:\Progra~1\Java\jdk1.5.0_02"
SET PATH=%JVMSTAT_HOME%\bat;%JAVA_HOME%\bin;%PATH%
remote test 수행 ( Host A와의 RMI 통신여부 확인 )
C:\jvmstat\bat\> jps 192.168.1.117
C:\jvmstat\bat\> jstat -gcutil rmi://11216@192.168.1.117 1000 10
- Host A의 Java Application 모니터링
상기의 설치 내용이 정상적으로 완료 확인
Host B에서
C:\jvmstat\bat\> visualgc 11216@192.168.1.117:1099 5000
11216 : vmid
192.168.1.117 : host A's IP Address
1099 : Host A's RMI TCP Port
5000 : Interval , millisecond
netstat의 TCP 연결 상태 의미
netstat의 State 필드에 표시되는 TCP 상태표시가 갖는 의미를 알아봅시다.
RFC 793 문서에 있는 TCP 기본 연결, 종료 과정을 보면 이해가 더 빠를 거라 생각한다.
-----------------------------------------------------------
# netstat -atn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
... 생략 ...
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN <-- 포트가 열렸음
tcp 0 0 192.168.123.10:32799 207.46.106.141:1863 ESTABLISHED <-- 서로 연결중
tcp 0 0 192.168.123.10:32794 218.xxx.xx.xx:22 ESTABLISHED
tcp 0 0 192.168.123.10:32802 207.46.108.46:1863 CLOSE_WAIT <-- 종료 대기중
tcp 0 0 192.168.123.10:33244 211.xxx.xx.x:80 ESTABLISHED
... 생략 ...
-----------------------------------------------------------
1) TCP 연결관련 상태
* RFC 793문서에 나온 기본적인 TCP 연결 과정
TCP A TCP B
1. CLOSED LISTEN
2. SYN-SENT --> < SEQ=100>< CTL=SYN> --> SYN-RECEIVED
3. ESTABLISHED <-- < SEQ=300>< ACK=101>< CTL=SYN,ACK> <-- SYN-RECEIVED
4. ESTABLISHED --> < SEQ=101>< ACK=301>< CTL=ACK> --> ESTABLISHED
5. ESTABLISHED --> < SEQ=101>< ACK=301>< CTL=ACK>< DATA> --> ESTABLISHED
LISTEN : 데몬이 요청을 발을 수 있도록 연결 요구를 기다리는 상태
즉, 포트가 열려있음을 의미. http(80), mail(25), ftp(21), telnet(23) 등
위에서 포트 25(mail)이 메일을 받을 수 있도록 열려 있는 상태
윈도우즈에서는 LISTENING으로 표시
SYN_SENT : 로컬에서 원격으로 연결 요청(SYN 신호를 보냄)을 시도한 상태
SYN_RECV : 원격으로 부터 연결 요청을 받은 상태
요청을 받아 SYN+ACK 신호로 응답은 한 상태이지만 ACK는 받지 못했다.
netstat로 확인할 때 SYN_RECV가 상당히 많다면 TCP SYN 플러딩(Flooding) 공격일
가능성이 있다.
윈도우즈와 솔라리스에서는 SYN_RECEIVED으로, FreeBSD는 SYN_RCVD으로 표시
ESTABLISHED : 서로 연결이 되어 있는 상태
위에서 192.168.123.10의 포트 32794과 218.xxx.xx.xx의 포트 22(ssh)이 서로
연결되어 있는 상태
2) TCP 종료관련 상태
* 정상적인 연결 종료 과정
TCP A TCP B
1. ESTABLISHED ESTABLISHED
2. (Close)
FIN-WAIT-1 --> < SEQ=100>< ACK=300>< CTL=FIN,ACK> --> CLOSE-WAIT
3. FIN-WAIT-2 <-- < SEQ=300>< ACK=101>< CTL=ACK> <-- CLOSE-WAIT
4. (Close)
TIME-WAIT <-- < SEQ=300>< ACK=101>< CTL=FIN,ACK> <-- LAST-ACK
5. TIME-WAIT --> < SEQ=101>< ACK=301>< CTL=ACK> --> CLOSED
6. (2 MSL)
CLOSED
FIN_WAIT1 : 소켓이 닫히고 연결이 종료되고 있는 상태. 원격의 응답은 받을 수 있다.
솔라리스에서는 FIN_WAIT_1로 표시
FIN_WAIT2 : 로컬이 원격으로 부터 연결 종료 요구를 기다리는 상태
솔라리스에서는 FIN_WAIT_2로 표시
CLOSE_WAIT : 원격의 연결 요청을 받고 연결이 종료되기를 기다리는 상태
원격으로 부터 FIN+ACK 신호를 받고 ACK 신호를 원격에 보냈다.
TIME_WAIT : 연결은 종료되었으나 원격의 수신 보장을 위해 기다리고 있는 상태
이 상태를 특히 자주 보게되는 Apache에서 KeepAlive를 OFF로 해둔 경우,
Tomcat 서버를 쓰는 경우 등
LAST_ACK : 연결은 종료되었고 승인을 기다리는 상태
CLOSED : 완전히 연결이 종료된 상태
※ 위의 FIN_WAIT1, FIN_WAIT2, CLOSE_WAIT 3개 상태는 연결 종료를 위해 서로간에
신호를 주고받는 과정에 나타나는 상태로 이해하면 된다.
종료 요청을 한 곳에서는 FIN_WAIT1, FIN_WAIT2, TIME_WAIT 상태가
종료 요청을 받는 곳에서는 CLOSE_WAIT, LAST_ACK 상태가 표시된다.
3) 기타
CLOSING : 연결은 종료되었으나 전송도중 데이타가 분실된 상태
UNKNOWN : 소켓의 상태를 알 수 없음
솔라리스의 netstat 명령에서는 다음 2개의 상태를 더 표시한다.
IDLE : 소켓이 열렸지만 binding 되지 않은 상태
BOUND : listen이나 연결을 위한 준비 상태
printStackTrace를 Log4j에 출력하기
package com.qnsolv.wipi.exception;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ExceptionUtil
{
Log log = null;
public ExceptionUtil( Object obj)
{
log = LogFactory.getLog(obj.getClass().getName());
}
public ExceptionUtil()
{
log = LogFactory.getLog(this.getClass().getName());
}
public void writePrintStckTrace(Exception e)
{
writePrintStckTrace(e, "");
}
public void writePrintStckTrace(Exception e, String MIN)
{
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream pinrtStream = new PrintStream(new ByteArrayOutputStream());
e.printStackTrace(pinrtStream);
String stackTraceString = out.toString();
log.error("MIN=" + MIN + ":" + stackTraceString.toString());
}
catch (Exception e2)
{
}
}
}