시스템을 잘 관리하기 위해서는 프로그램을 주기적으로 Restart 해주는 것이 좋다. 서버를 Restart하면 더 좋고! 하지만, 대부분의 시스템은 복잡하게 얽혀 있어 시스템을 재시작하는 건 간단하지 않다. 신경 쓸 것이 한 두개가 아니다.
그중에 가장 신경 써야 하는 건 고객들! 정해진 시간 동안 시스템에 접근할 수 없다고 고객에게 공지해야 한다. 그리고 정상적으로 연결 되었는지 확인하라고 요청해야 한다. 고객들에게 정중하게 메일을 보낸다.
"고객님, 시스템 휴지가 있습니다.
2시간 동안 시스템 접근이 불가능합니다."
문제가 발생하자 고객은 일단 메일을 받은 적이 없다고 우긴다.
결국, 우린 너무 고귀해서 모니터링
같은거 못하겠다고 한다. 시스템 모니터링
은 너희가 해줘야 하는 서비스라고 한다.
고객님! 이러시면 안 되요! 👿
내가 관리하는 시스템은 서버 역할하고 고객 시스템은 클라이언트 역할을 한다. 서버와 클라이언트가 연결되어 있는 상태에서 서버를 재 시작한다. 서버는 어떤 클라이언트가 성공적으로 연결되었는지 알 수 있으나, 연결되지 않은 클라이언트가 어떤 상태인지는 알 수 없다.
시스템 상태는 로그에 쓰여진다. 우린 로그만 있으면 고객 시스템의 상태를 확인 할 수 있다.
로그
를 수집하자!고객의 요구사항은 다음과 같다.
내가 관리하는 시스템의 로깅 환경부터 확인한다.
나는 이 문제를 SocketAppender
를 이용해 풀어보려한다. 일단 컨셉일 뿐이고 대용량 시스템에 어떻게 적용해야 할지는 꽤나 많은 검증이 필요하다. 아래 소스코드는 Github 에서 확인 가능하다.
SocketAppender
를 사용한다.SocketAppender
를 선택한 이유는 3가지 이다.
SocketAppender
를 위한 Input Plugins를 제공 함SocketAppender
는 고객 요구사항에 완벽하게 부합한다.
SimpleSocketServer
실행시키자!SimpleSocketServer
는 특정 Port
로 부터 송신된 로그를 수신한다. 그리고 자체적으로 로그를 생성한다. 사용 방법은 매우 단순하며, log4j1.2
Javadoc에서 확인 할 수 있다.
Usage: java org.apache.log4j.net.SimpleSocketServer port configFile
where port is a part number where the server listens and
configFile is a configuration file fed to the PropertyConfigurator or to DOMConfigurator if an XML file.
SimpleSocketServer
가 사용하는 <Port>
는 9999
를 사용하기로 한다.
자제적으로 생성하는 로그는 <configFile>
을 통해 설정하는데, 단순하게 콘솔화면으로 출력하도록 구성한다.
# log4j-server.properties
log4j.rootLogger=INFO,stdout
# stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%t :: %d :: %m%n
위 내용을 log4j-server.properties
파일로 적당한 위치에 저장한다. 나 같은 경우는 D:/log4j-socket-server
에 저장하였다. 그리고 아래 명령으로 서버를 실행한다.
java -classpath d:/log4j-socket-server/Log4j-1.2.11.jar org.apache.log4j.net.SimpleSocketServer 9999 D:/log4j-socket-server/log4j-server.properties
SocketAppender
구성하자!다음으로 SimpleSocketServer
로 로그를 전송하는 SocketAppender
를 구성하자. SocketAppender
는 LoggingEvent
객체를 원격 로그 서버로 전송하는 역할을 담당한다.
SocketAppender
의 특성은 log4j1.2
Javadoc 에서 확인 할 수 있다.
내가 관리하는 시스템은 Programatically 하게 log4j
를 사용하므로 아래와 같이 Log4jSocketAppenderTest.java
를 작성하여 실행한다.
package com.choong.log4j.test;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.net.SocketAppender;
public class Log4jSocketAppenderTest {
public static void main(String[] args) {
Logger logger = Logger.getLogger(Log4jSocketAppenderTest.class);
PatternLayout patternLayout = new PatternLayout("%t :: %d :: %m%n");
ConsoleAppender consoleAppender = new ConsoleAppender(patternLayout);
SocketAppender socketAppender = new SocketAppender("localhost", 9999);
logger.addAppender(consoleAppender);
logger.addAppender(socketAppender);
logger.info("Hello, ChoongYul!");
}
}
SimpleSocketServer
출력결과마지막으로 SimpleSocketServer
의 출력결과를 확인한다.
ouput:
D:\>java -classpath d:/log4j-socket-server/Log4j-1.2.11.jar org.apache.log4j.net.SimpleSocketServer 9999 D:/log4j-socket-server/log4j-server.properties
main :: 2023-01-08 12:57:10,386 :: Listening on port 9999
main :: 2023-01-08 12:57:10,417 :: Waiting to accept a new client.
main :: 2023-01-08 12:57:25,681 :: Connected to client at /127.0.0.1
main :: 2023-01-08 12:57:25,682 :: Starting new socket node.
main :: 2023-01-08 12:57:26,117 :: Waiting to accept a new client.
main :: 2023-01-08 12:57:25,774 :: Hello, ChoongYul!
Thread-0 :: 2023-01-08 12:57:26,385 :: Caught java.net.SocketException closing conneciton.
SimpleSocketServer
는 log4j-server.properties
에서 설정한 ConsoleAppender
를 통해 'Hello, ChoongYul!'을 출력하였다.