본 게시글은 이상민 저자의 자바 트러블슈팅 책을 읽고 공부한 내용을 정리한 글이다.
스프링부트와 scouter를 연동하기 전에 먼저 scouter를 구성하는 기능들을 살펴보겠다.
scouter 서버
- scouter 서버의 주요 역할은 다음과 같다.
- 에이전트에서 전송한 데이터 수집 및 저장
- API 제공(scouter-paper 등을 사용할 때 필요)
- 집킨을 사용할 경우 집킨으로의 데이터 전송
- scouter 서버는 Scala라는 언어로 되어 있으나, 스칼라는 자바 기반의 JVM에서 실행되는
언어이기 때문에, 컴퓨터에 자바만 설치외어 있으면 큰 문제 없이 실행할 수 있다고 한다. - scouter 서버는 컬렉터라고 부르기도 하는데, 대부분 서버라고 부른다고 한다.
- 다운받은 scouter 파일을 살펴보면 server라는 디렉토리가 존재한다.
이 디렉토리 내에 서버를 띄우고 중지시키는 스크립트들과 설정 파일 등이 존재한다.
- startup.sh/ startup.bat: 스카우터 서버를 시작하는 스크립트다.
- stop.sh/ stop.bat: 스카우터를 종료하는 스크립트다.
- conf: 설정 파일이 저장되어 있는 디렉터리다.
- database: 수집한 데이터를 저장하는 디렉터리다.
- logs: 서버의 로그 디렉터리다.
서버의 conf에 대해 더 자세히 알아보자
Server Conf
- conf에 들어가면 여러 옵션이 있다. 그 중 꼭 알아야 할 옵션에 대해 살펴보자
- server_id: scouter 서버의 ID다. 만약 설정하지 않았을 경우 해당 서버의 호스트 이름이 서버 이름으로 나타난다.
반드시 이 설정을 해야 하는 것은 아니지만, 수집 서버가 여러 대 있을 경우에는 이 이름을 지정해 줘야 구분하기 쉬워진다. - net_tcp_listen_port: 서버가 대기하고 있는 TCP 포트 번호다.
- net_udp_listen_port: 서버가 대기하고 있는 UDP 포트 번호다.
- db_dir: 파일 기반으로 저장되는 데이터의 경로를 지정한다.
- log_dir: 스카우터 서버도 로그를 남기는데, 그 로그의 경로를 지정한다. 만약 존재하지 않는
디렉터리를 지정할 경우 정상적으로 시작되지 않을 수 있다고 한다.
- server_id: scouter 서버의 ID다. 만약 설정하지 않았을 경우 해당 서버의 호스트 이름이 서버 이름으로 나타난다.
한 대의 서버에서 여러 서버의 정보 수집하기
- 한 대의 서버에서 하나의 scouter 서버만 띄워서 사용하는 경우가 많은데,
작은 서비스는 괜찮지만 큰 서비스의 경우 서비스별로 분리가 되지 않아 사용하기 불편한 점이 많다고 한다. - 이 경우 XLog나 나머지 그래프에 하나로 묶여서 나오기 때문에, 장애가 발생 했을 경우 어떤 서버군에서 장애가 발생했는지
알아내기가 매우 어려워진다고 한다. - 이 경우 다음과 같이 수집 서버 시작 스크립트의 자바 시작 옵션에 다음 내용을 추가해 준다.
- -Dscouter.cofig=/scouter/server/conf/member.conf
- 예를 들어, 전시를 처리하기 위한 수집 서버와 회원 정보를 관리하는 수집 서버가 있다고 가정해 보자.
- 그러면 먼저 display.conf, member.conf 파일을 server/conf/에 만들어 놓는다.
- 여기서 중요한 것은 포트 번호와 db_dir, log_dir을 다르게 설정해놓는 것이다.
- 수집 서버마다 값을 다르게 설정한 후
- 위에 적힌 명령어를 통해 여러 개의 터미널을 실행하면,
하나의 서버에서 각각 다른 저장소를 사용하는 두 개의 scouter 서버 인스턴스가 동작하게 된다.
한 대의 서버에서 최대로 수집 가능한 TPS는 1000이라고 한다.
만약 모니터링하는 서버의 TPS가 1000을 넘긴다면 해당 서버는 따로 분리해서 모니터링을 해주도록 하자.
TPS: Transaction Per Seconds의 약자로 초당 처리량을 의미한다.
scouter 호스트 에이전트
- 스카우터에서 에이전트는 데이터를 취합해서 수집 서버로 전달하는 역할을 하는 것을 의미한다.
- 스카우터에서 제공하는 에이전트는 크게 세 가지가 있다.
- 호스트 에이전트
- 자바 에이전트
- 배치 에이전트
- 이 중 호스트 에이전트에 대해 먼저 살펴보자
호스트 에이전트
- 서버의 리소스 상태 데이터들을 취합하여 전송
- CPU
- 메모리
- 네트워크
- 디스크
- 반드시 설정해야 하는 사항은 다음과 같다.
- net_collector_ip: 앞에서 설정한 수집 서버의 IP를 지정한다.
- net_collector_tcp_port: 수집 서버의 TCP 포트를 지정한다.
- net_collector_udp_port: 수집 서버의 UDP 포트를 지정한다.
- 이제 설정이 끝났으면 host.sh를 정보 수집하려는 서버에서 실행시키면 된다.
자바 에이전트
- 자바 에이전트는 Tomcat이나 Jetty 등 자바 기반의 WAS를 모니터링하거나
우리가 만든 Demon 프로그램을 모니터링 할 수도 있다. - 웬만한 자바 프로그램은 전부 모니터링이 가능하다고 보면 된다.
- 자바 에이전트를 수행하기 위해서 WAS 시작 옵션에 에이전트 지정을 해줘야한다.
- SCOUTER_AGENT_DIR=${SCOUTER_HOME_위치}/scouter/agent.java
- JAVA_OPTS=" ${JAVA_OPTS} -javaagent:${SCOUTER_AGENT_DIR}/scouter.agent.jar"
- JAVA_OPTS=" ${JAVA_OPTS} -DSCOUTER.config=${SCOUTER_AGENT_DIR}/scouter.conf"
- 를 설정하면 된다. 우리는 scouter home의 위치와 scouter agent의 위치만 잘 설정해주면 된다.
- 이제 에이전트 설정 파일을 살펴보자
- obj_name=수집서버1
- net_collector_ip: 앞에서 설정한 수집 서버의 IP를 지정한다.
- net_collector_tcp_port: 수집 서버의 TCP 포트를 지정한다.
- net_collector_udp_port: 수집 서버의 UDP 포트를 지정한다.
- 아까 살펴봤던 것과 다른 점 하나는 obj_name이다.
- 자바 에이전트의 경우는 인스턴스 하나만 띄워서 사용하는 경우가 거의 없기 때문에
이처럼 이름을 지정해서 사용해주는 걸 권장한다고 한다.
자바의 ClassFileTransformer
- 자바에는 java.lang.instrument라는 패키지가 있다.
- 이 패키지에는 ClassFileTransformer라는 인터페이가 존재한다.
- 스카우터 설정에서 javaagent:jar파일 설정을 봤을 것이다.
- 이렇게 javaagent: 옵션을 설정해 줄 경우 JVM이 시작되면 ClassFileTransformer 인터페이스를 구현한 클래스를 찾고,
특정 클래스가 로딩 될 때마다, ClassFileTransformer의 transform() 메서드를 호출해
클래스를 바이트 배열로 넘기고, 넘어온 내용을 수정한 후 JVM에 바이트 배열로 돌려준다. - 이 변환 작업을 통해 특정 클래스가 로드되거나 하면 어떤 쿼리를 수행하였는지, 어떤 메서드를 얼마나 수행했는지,
어떤 API가 호출되었는지를 알 수 있다고 한다. - 이 변환 작업의 단점은 JVM이 시작될 때 호출된다는 점이다. 요즘엔 실시간으로 반영이 가능하지만,
cpu가 100%에 육박할 수 있기 때문에, 중간에 scouter 관련 설정을 바꾼다면 반드시 재시작을 해주라고 한다. - scouter에서 변환과 관련된 옵션은 대부분 hook_로 시작한다고 한다.
이제 기본적인 공부는 끝났으니, 진짜로 스프링 부트 WAS를 모니터링 해보도록 하자.
스프링 부트에 자바 에이전트 실행하기
- 아까 위에서 설명했듯이 WAS 시작 옵션에
- SCOUTER_AGENT_DIR=${SCOUTER_HOME_위치}/scouter/agent.java
- JAVA_OPTS=" ${JAVA_OPTS} -javaagent:${SCOUTER_AGENT_DIR}/scouter.agent.jar"
- JAVA_OPTS=" ${JAVA_OPTS} -DSCOUTER.config=${SCOUTER_AGENT_DIR}/scouter.conf"
- 이 세 가지를 정의해주어야 한다.
- 자르 파일을 빌드하고 해당 자르 파일을 실행할 때 위의 명령어를 적용하는 방식과
- Gradle에 직접 위의 명령어를 적용해 빌드하는 방식이 존재하는데, 나는 간단하게 Gradle에 명령어를 작성해주었다.
bootRun {
jvmArgs = [
"-javaagent:{경로}/scouter/agent.java/scouter.agent.jar",
"-DSCOUTER.config={경로}/scouter/agent.java/scouter.conf"
]
}
- 이렇게 설정해준 후 gradle로 빌드하면 끝!
- ./gradlew bootRun을 실행하면
- 이렇게 정상적으로 작동이 된다.
- 이제 클라이언트에 접속해서 연결이 잘 됐는지 확인해보자
- 내 노트북에 host agent를 실행하고 springboot was에 java agent를 실행한 결과
- 위와 같이 cpu, 메모리, 트랜잭션까지 전부 잘 잡히는 것을 볼 수 있다.
- 로컬에서 모니터링 해보기 성공 !
'APM > Scouter' 카테고리의 다른 글
[자바 트러블슈팅 공부] XLog(필터링, 통계), PlugIn, Scouter 사용시 유용한 팁 (0) | 2025.01.15 |
---|---|
[자바 트러블슈팅 공부] Scouter 그래프 보는 법 및 Xlog 보는 방법 (1) | 2024.12.31 |
[자바 트러블슈팅 공부] 각종 메뉴와 필수 그래프 항목 (2) | 2024.12.27 |
[자바 트러블슈팅 공부] APM이란?, 스카우터 기본 세팅 (1) | 2024.12.19 |