Pam
Pam 블로그 주인장

사용자 없는 서비스 성능 테스트하기 (1) - Scouter

사용자 없는 서비스 성능 테스트하기 (1) - Scouter


image

개요

세차새차에서 일하면서 Datadog을 써볼 기회가 있었다!

그러나 여러 문제가 겹치면서 (1. Elastic beanstalk의 Auto Scaling에 의해 datadog agent가 자꾸 삭제됨, 2. 내가 마음대로 인프라를 손댈수 없었음, 3. 세차새차 측에서도 잘 돌아가고 있는 인프라를 손대가며 datadog을 사용하고싶진 않으신듯…, 4. Datadog 너무 비싸다) 실제로 APM을 사용해볼 기회는 없었다

APM을 직접 사용해볼 기회를 놓친게 아쉬운 마음을 뒤로하고, 새로운 프로젝트인 SOFO를 개발하며 성능 향상을 어떻게 실현하면 좋을지 고민이 됐다.

SOFO는 아직 개발단계인, 사용자가 0인 서비스였기 때문에…

그러나 최근에 인강을 들으며 좋은 아이디어를 스쳐가듯 배우게 되었고, APM 사용과 SOFO 성능 향상을 동시에 실천해보려 한다!

이번 게시글에서 다룰 내용은 아래와 같다.

Scouter 설치 및 실행

추후 게시글에서는 JMeter를 사용하여 애플리케이션에 성능을 테스트하고, Scouter를 통해 문제가 되는 부분을 파악하고 수정해 SOFO의 성능을 향상시킬 것이다.

Scouter

image

Scouter는 AgentCollector, 그리고 Client(Viewer) 프로그램으로 구성된다.

  • Agent: WAS와 호스트 PC의 성능 지표를 수집하는 핵심 도구
    • Java Agent: 애플리케이션에 부착되어 애플리케이션 성능 지표 수집
    • Host Agent: 호스트 PC에 부착되어 호스트 PC 성능 지표 수집
  • Collector: Agent로부터 모든 성능 지표를 수집
  • Client: Collector로부터 성능 지표를 받아 사용자 친화적 인터페이스로 시각화

Scouter Agent 설치

  • Scouter ReadMe (한국 개발이라 그런가 한글 버전도 있었던거 같으니 찾아보길…)

image

이번에 내가 다룰 인프라 구조도는 위와 같다.

나는 Host agent와 Collector를 Ec2에 설치하는 방식으로 사용했는데, Docker를 사용하는 편이 나을 거 같다. (이후 리팩토링하면 추가하겠음…)

Scouter Agent & Collector 파일 다운

2025.01.03 기준 Scouter 최신 버전은 scouter-all-2.20.0.tar.gz이다.

scouter-all-xxx 파일은 Agent와 Collector가 묶여있는 파일이다. Ec2에 설치 후 압축해제하도록 하자.

1
2
3
wget https://github.com/scouter-project/scouter/releases/download/v2.20.0/scouter-all-2.20.0.tar.gz
tar -xvf [scouter-all-2.20.0.tar.gz](https://github.com/scouter-project/scouter/releases/download/v2.20.0/scouter-all-2.20.0.tar.gz)
rm scouter-all-2.20.0.tar.gz 

image

설치 후 Scouter 폴더 구조는 위와 같다.


사전 작업

6100 port open

image

Scouter는 기본적으로 6100 포트를 사용하여 통신하기 때문에 Ec2의 인바운드 규칙에 6100 포트를 추가해주자.

Java 8 설치

1
sudo apt install openjdk-8-jdk

local에서 잠깐 테스트해보았을때 이러한 문제가 있어서 Ec2에선 애초에 Java 11버전을 다운로드 했다.는데 동작하지 않아 다시 찾아보니 Scouter Server는 java 8에서만 동작한다고 한다… (?)

  • 참고: https://0andwild.tistory.com/44

JDK 1.8을 다운받도록 하자…


Collector Server 실행

실행

1
sh ./server/startup.sh

image

정상적으로 Collector가 실행되었다.


Host Agent 실행

scouter.conf 작성

1
vi ./agent.host/conf/scouter.conf
1
2
3
4
5
6
7
8
9
10
11
### scouter host configruation sample
net_collector_ip=127.0.0.1
net_collector_udp_port=6100
net_collector_tcp_port=6100
#cpu_warning_pct=80
#cpu_fatal_pct=85
#cpu_check_period_ms=60000
#cpu_fatal_history=3
#cpu_alert_interval_ms=300000
#disk_warning_pct=88
#disk_fatal_pct=92

기본 코드의 위 3 라인만 주석해제한다.

Collector와 Host Agent가 동일 서버 위에 존재하기 때문에 net_collector_ip는 Localhost로 해주었다. Collector를 다른 서버로 빼면 좋을 거 같긴 하지만 AWS 프리티어 문제로….😅

실행

1
2
3
4
5
#!/usr/bin/env bash

nohup java  -classpath ./scouter.host.jar scouter.boot.Boot ./lib > nohup.out &
sleep 1
tail -100 nohup.out
1
sh ./host.sh

참고로 host.sh 코드가 동일 위치에 있는 scouter.host.jar을 가리키고 있기 때문에 sh 파일과 동일한 위치에서 실행시켜야 된다…


Java Agent 실행

애플리케이션에 Java Agent를 부탁하기 전에 먼저 Client를 통해 Collector와 Host Agent가 정상동작하는지 먼저 확인해보는것이 좋겠다.

Ec2 위에 WAS를 돌리고 있는 경우 Scouter.conf를 수정하고, 애플리케이션 실행 코드를 수정하는 걸로 간단히 Java Agent를 실행할수 있지만, 나는 Docker 위에 애플리케이션을 띄어놓았기 때문에 Dockerfile을 수정해야했다.

scouter.conf 수정

1
vi ./agent.java/conf/scouter.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
### scouter java agent configuration sample
#obj_name=WAS-01
net_collector_ip={ec2 private ip}
net_collector_udp_port=6100
net_collector_tcp_port=6100
#hook_method_patterns=sample.mybiz.*Biz.*,sample.service.*Service.*
#trace_http_client_ip_header_key=X-Forwarded-For
#profile_spring_controller_method_parameter_enabled=false
#hook_exception_class_patterns=my.exception.TypedException
#profile_fullstack_hooked_exception_enabled=true
#hook_exception_handler_method_patterns=my.AbstractAPIController.fallbackHandler,my.ApiExceptionLoggingFilter.handleNotFoundd
ErrorResponse
#hook_exception_hanlder_exclude_class_patterns=exception.BizException
~                                                                        

우선 Java Agent의 설정파일을 수정한다.

현재 Ec2위에 Scouter Server가 떠있으므로 Collector ip는 Ec2의 사설 주소로 한다.

Back.Dockerfile 수정

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
31
# 기존
FROM openjdk:17-jdk-slim
WORKDIR /app

COPY soundflyer-infra/deploy/docker/data/server/MusicPlatform-0.0.1-SNAPSHOT.jar .

ENTRYPOINT [ \
    "java", \
    "-Dspring.profiles.active=dev", \
    "-Duser.timezone=Asia/Seoul", \
    "-jar", \
    "MusicPlatform-0.0.1-SNAPSHOT.jar" \
]

# 수정    
FROM openjdk:17-jdk-slim
WORKDIR /app

COPY soundflyer-infra/deploy/docker/data/server/MusicPlatform-0.0.1-SNAPSHOT.jar .
COPY apm/scouter/agent.java/scouter.agent.jar .
COPY apm/scouter/agent.java/conf/scouter.conf .

ENTRYPOINT [ \
    "java", \
    "-javaagent:/app/scouter.agent.jar", \
    "-Dscouter.config=/app/scouter.conf", \
    "-Dspring.profiles.active=dev", \
    "-Duser.timezone=Asia/Seoul", \
    "-jar", \
    "MusicPlatform-0.0.1-SNAPSHOT.jar" \
]

Docker 컨텍스트에 scouter.agent.jar과 설정파일을 복사해온 후 애플리케이션을 실행 시킬 때 부착해주었다.


image

백엔드 컨테이너 로그를 살펴보면 Spring 실행 전에 Scouter가 정상적으로 실행되었음을 확인할 수 있다.


Client 설치

클라이언트 PC에는 java 11이상이 설치되어 있어야한다.

1
xattr -cr scouter.client.app

Scouter Client 파일을 다운 및 압축해제 한 후 확장 속성을 삭제해주자.

image

나는 더블 클릭으로 실행이 안되어서 scouter.client/Contents/MacOS/scouter를 직접 실행시켰다.

Server Address: {Ec2 public ip}:6100
ID: admin(초기값)
Password: (초기값)


Scouter 모니터링

image

Host만 연결되고 WAS는 연결되지 않은 모습이다.

살펴보면 object 창에 Linux만 존재하는 것을 볼 수 있다. Host Agent는 Host pc의 정보를 수집하기에 EC2의 CPU 수치는 정상적으로 수집되는 것을 확인할 수 있다.

image

WAS 연결 후 모습이다. Object에 tomcat이 추가적으로 연결된 걸 확인할 수 있다.

  • Recent User: 최근 활성화된 사용자의 수
  • TPS(Transaction Per Second): 초당 얼마나 많은 요청을 처리가능한지 보여주는 지표
  • Elapsed Time: 작업 완료에 걸리는 시간. 사용자 입장에서의 응답시간.
  • Heap Used: JVM이 사용하고 있는 Heap 메모리. Garbage Collection 효율을 확인할 수 있다.
  • XLog: 트랜젝션 실행 정보를 시각화해준다.




다음 게시글에서는 JMeter를 사용하여 부하를 일으키고, 애플리케이션에서 성능이 떨어지는 부분을 확인한 다음에 성능을 개선하는 내용을 작성해볼 예정이다