1. 데몬(daemon) 이란?
주기적인 서비스 요청을 처리하기 위해서 커널상에 백그라운드 모드로 실행되는 프로세스로, 메모리 관리 방법에 따라 단독 데몬과 xinetd로 분리된다.
- 단독데몬
항상 백그라운드 모드로 실행되고 메모리를 상대적으로 많이 소비한다. 그러나 서비스(응답속도)가 빠르다. httpd와 같은 웹서비스 데몬이 대표적. - xinetd(슈퍼데몬)
요청이 있을때마다 xinetd가 서비스를 싱행시켜주므로 메모리 소비가 적다. 그러나 단독데몬에 비해 상대적으로 서비스 속도가 느리다.
2. 간단한 자바 데몬 만들기
nohup을 이용해서 java를 실행시킨다.
터미널이 종료될 때(쉘이 종료될 때) 프로세스가 죽는 이유는 해당 프로세스가 쉘의 자식 프로세스 이기 때문이다. 따라서, 부모 프로세스가 죽을대 던지는 SIGHUP을 자식 프로세스가 받게 된다.
nohup은 부모 프로세스가 죽을때 자식 프로세스에게 SIGHUP을 던지지 않는 프로세스를 말한다.
$ nohup java 클래스명 & |
사용하기 편한 장점은 있으나, 문제는 중지를 시킬수 없다. 즉, 해당 프로세스 ID를 찾아내 kill하는 수 밖에 없다. 물론 파일 체크 기법, 소켓을 이용한 제어 방법등을 사용할 수 있지만 스스로 구현해야 하는 번거로움이 있다.
3. apache commons daemon 이용하기
Java는 UNIX의 시그널 처리를 할수 없기때문에, 중지 신호(TERM signal)를 처리하기 위해서는 따로 구현을 해야한다.
이런 번거로움을 해결하기 위해 자카르타의 하위 프로젝트중의 commons daemon을 이용한다. commons daemon은
중지 신호를 받으면 미리 지정된 메소드를 실행한다.
** 다운로드: http://commons.apache.org/daemon/
UNIX용 Jsvc와 윈도우용 Procrun 있다.
여기서는 Jsvc를 이용해보도록 하겠다.
commons daemon을 다운로드해 압축을 해제하면 위 그림과 같다.
commons-daemon.jar 파일은 Java프로젝트 lib폴더에 복사해둔다.
bin폴더의 압축파일을 해제하면 jsvc-src라는 폴더가 나온다.
폴더의 내용은 위와 같다.
commons daemon을 사용하기 위해서는 바로 여기서 jsvc를 빌드해줘야 한다.
빌드환경은 다음과 같다.(리눅스에서 빌드해야한다.)
- GNU AutoConf(at least 2.53)
- ANSI-C compliant compiler(GCC is good)
- GNU Make
- A Java Platform 2 compliant SDK
여기서부터는 ubuntu 8.10 환경에서 진행하도록 한다.
먼저 JDK가 설치되어 있지 않다면 JDK를 설치한다.
$ sudo apt-get install sun-java6-jdk |
JDK가 설치되는 경로는 /usr/lib/jvm/java-6-sun 이다.
gcc 및 make 가 설치되있지 않다면 아래 명령를 이용해 한방에 설치한다.
$ sudo apt-get install build-essential |
AutoConf가 설치되있지 않다면 AutoConf를 설치한다.
$ sudo apt-get install autoconf |
Jsvc를 빌드하는 방법은 다음과 같다.
- support/buildconf.sh
- ./configure --with-java=/usr/lib/jvm/java-6-sun
- make
빌드가 성공적으로 이루어졌다면 위 그림과 같이 jsvc가 만들어진것을 확인할 수 있다. 이후 이 파일을 가지고 Java 데몬을 실행한다.
Java 데몬을 만들려면 org.apache.commons.daemon.Daemon 인터페이스의 init, start, stop, destory 메소드를 구현해야 한다.
샘플 코드는 아래와 같다.
import org.apache.commons.daemon.Daemon; import org.apache.commons.daemon.DaemonContext; public class DaemonTest implements Daemon { Thread t = null; @Override public void init(DaemonContext arg0) throws Exception { System.err.println("daemonTest init"); t = new DaemonThread(); } @Override public void start() throws Exception { System.err.println("daemonTest start"); t.start(); } @Override public void stop() throws Exception { System.err.println("daemonTest stop"); t.interrupt(); } @Override public void destroy() { System.err.println("daemonTest destroy"); } }
public class DaemonThread extends Thread { @Override public void run() { while( Thread.interrupted() ) { System.err.println("run"); try { Thread.sleep(5000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } } }init에서 초기화, start에서 처리할 작업을 별도의 쓰레드로 생성해서 실행한다. start 메소드 호출후 반드시 return 되어야 데몬이 시그널 처리를 제대로 할 수 있다.
stop, destroy 는 중지 신호가 오면 차례되로 호출된다.
이제 실행/중지 스크립트를 작성한다.
Jsvc를 싱행하는데 필요한것은 실행하는 계정(user), JAVA_HOME(-home), 프로세스ID 파일(-pidfile), 출력지정(-outfile, -errfile), 클래스파일(-cp) 등이 있다.
#!/bin/sh JAVA_HOME=/usr/lib/jvm/java-6-sun DAEMON_HOME=/home/lyb1495/commons-daemon-1.0.1/bin/jsvc-src DAEMON_USER=lyb1495 DAEMONTEST_HOME=/home/lyb1495/workspace/Daemon PID_FILE=$DAEMONTEST_HOME/daemon_test.pid CLASSPATH=\ $DAEMONTEST_HOME/bin:\ $DAEMONTEST_HOME/lib/commons-daemon.jar case "$1" in start) # # Start Daemon # $DAEMON_HOME/jsvc \ -user $DAEMON_USER \ -home $JAVA_HOME \ -wait 10 \ -pidfile $PID_FILE \ -errfile '&1' \ -cp $CLASSPATH \ DaemonTest # # To get a verbose JVM #-verbose \ # To get a debug of jsvc. #-debug \ exit $? ;; stop) # # Stop PostMan # $DAEMON_HOME/jsvc \ -stop \ -pidfile $PID_FILE \ DaemonTest exit $? ;; # *) echo "Usage DaemonTest.sh start/stop" exit 1;; esac이제 Java 데몬을 실행하기 위한 모든 준비를 마쳤다.
위에서 작성한 스크립트 파일을 이용해 Java 데몬을 실핸한다.
정상적으로 데몬이 시작된다면 PID_FILE에 지정한 파일이 생성된것을 확인할 수 있다.
'Development > Java' 카테고리의 다른 글
java 역어셈블러와 역컴파일러 (0) | 2012.01.23 |
---|---|
자바 네트워크 구동 프로토콜(JNLP)과 참조 구현, 자바 웹 스타트 (0) | 2012.01.18 |
Hotspot JVM의 Garbage Collector (0) | 2012.01.18 |
java - RMI (0) | 2012.01.17 |
자바 SimpleDateFormat (0) | 2011.01.24 |