∙Monitoring

Pinpoint 활용한 실시간 성능 모니터링 구축기

coor 2024. 10. 3. 12:42
 

 

 

nGrinder로 동시 요청 성능 테스트를 하던 중, 예상보다 성공 수가 적어 실시간으로 성공/실패 상황을 모니터링할 수 있는 도구를 찾던 과정에서 Pinpoint 알게 되어, 이번 글에는 Pinpoint에 대해 알아보았던 것과 이를 운영 서버에 적용하는 과정을 공유하려고 합니다.

 

 

 

1. Pinpoint 란?


Pinpoint는 네이버에서 만든 APM (Application Performance Management) 도구로, 분산된 애플리케이션의 성능을 모니터링하고 분석하는 데 사용됩니다. 실시간으로 애플리케이션의 서버맵, 실시간 활성 스레드 차트, 요청/응답 차트, API 호출 상세 기록, 서버의 상태성능을 추적하고, 문제 발생 시 그 원인을 쉽게 찾을 수 있습니다.

실제 운영 서버 화면

 

 

 

 

 

2. Pinpoint 구성 요소


Pinpoint 구성 요소는 Agent, Collector, Web, HBase 4가지 구성되어 있습니다.

  • Agent는 현재 수집해야 되는 애플리케이션을 의미합니다. 
  • Collector는 Agent으로부터 수집한 데이터를 받아서 HBase에 저장하는 중간 통로 역할을 합니다.
  • Web는 개발자 및 사용자들이 성능을 시각적으로 확인할 수 있는 웹 인터페이스입니다.
  • HBase는 성능 데이터를 저장하는 데이터베이스입니다.

 

 

 

 

3. 호환성 확인


Pinpoint 적용하기 앞서 Java의 버전에 따라서 Agent, Collector, Web, HBase 설치해야 합니다.
버전 호환성 관련된 부분은 Pinpoint Github에서 확인할 수 있습니다. 

자신의 개발환경이 자바 8 버전이면 이런 식으로 설치를 추천드립니다.
Agent : 2.0.x ~ 2.3.x
Collector : 2.0.x ~ 2.3.x
Web : 2.0.x ~ 2.3.x
HBase : 1.x

 

 

자바 17버전이면 이런 식으로 설치를 추천드립니다.
Agent : 3.0.x
Collector : 3.0.x
Web : 3.0.x
HBase : 2.x

 

 

저는 무작정 다른 사람의 글을 보고 따라 했다가 버전이 맞지 않아서 오류를 만났습니다.

Exception in thread "main" java.lang.UnsupportedClassVersionError: com/navercorp/pinpoint/web/WebApp has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 52.0

이 에러는 자바 애플리케이션이 현재 사용 중인 자바 런타임 버전보다 더 최신 버전으로 컴파일되었을 때 발생하는 에러입니다.
그래서 다시 제 Java 버전에 맞는 Pinpoint 설치하여 진행했습니다...😪

 

 

 

 

개발환경 : AWS EC2, Java 17

4. 운영서버 적용하기


[ 서버 구성 ]

서버 구성은 2대로 구성하였습니다.

  • 서버 1 : Agent를 설치해서 Java 프로젝트 실행
  • 서버 2 : Hbase, Collector, Web을 모두 설치하여 모니터링

 

기존에는 서버 1대로 Agent, Hbase, Collector, Web 설치해서 진행하려고 했지만 
AWS의 최소 사양인 t2.micro 인스턴스로는(1 vCPU와 1GB RAM) 실행할 수 없었습니다.
HBase가 많은 자원을 많이 소모하기 때문에 서버 과부하로 인해서 자주 죽었습니다...😪
그래서 모니터링 서버는 t3.small (2 vCPU, 2GB RAM) 진행하였습니다.

 

 

 

[ 설치 방법 ]

저는 자바 17 사용하고 있어서 3.0.x 버전 설치를 해야 했습니다.
버전 넘버는 Pinpoint 오픈 소스의 3.0.0 릴리즈 노트를 참고하여 설치하였습니다.

 

1. EC2 구성

Agent 설치할 서버와 Hbase, Collector, Web 모두 설치할 서버를 구성합니다.
EC2를 설치하는 것은 해당 내용과 관련이 없어서 별도로 가이드는 없이 진행하겠습니다.

 

 

다만 주의해야 하는 부분은 pinpoint 인스턴스 서버의 보안 그룹 인바운드에는 9991 ~ 9993까지는 필수로 포함되어야 합니다.
이유는 Agent가 Collector로 로그 전송을 할 때 사용하는 tcp 포트가 9991 ~ 9993까지가 기본값으로 되어있기 때문입니다.

(저는 8000-9990 포트 인바운드 포함시켰습니다)

 

 

그리고 자바 jdk 설치해야 합니다. 
Pinpoint가 Java 기반 모니터링 도구이기 때문에, JDK는 Pinpoint의 실행 환경을 제공하는 필수 요소입니다.

 

 

 

 

2. Hbase 설치

Hbase 아카이브 사이트로 이동하여 2.5.8 버전의 tar.gz 파일 다운로드 링크를 확인합니다.
2.x.x 버전 중에서 최대한 최신 버전을 선택하였습니다.

 

그리고 pinpoint 인스턴스 서버에 접속하여 wget으로 해당 압축파일을 다운로드합니다.

wget https://archive.apache.org/dist/hbase/2.5.8/hbase-2.5.8-bin.tar.gz

 

다운로드한 압축파일을 압축 해제합니다.

tar xzf hbase-2.5.8-bin.tar.gz

 

압축해제가 끝났으면 해당 디렉터리에 편하게 접근할 수 있도록 link를 걸겠습니다.

ln -s hbase-2.5.8 hbase

 

이렇게 하면 설치는 끝이 납니다. 
설치된 Hbase를 Hbase를 실행시킵니다.

hbase/bin/start-hbase.sh

 

다음으로는 Pinpoint 정보를 담을 테이블을 생성해야 합니다.
이에 대해서는 이미 Pinpoint가 스크립트를 지원하기 때문에 해당 스크립트를 통해 다운로드 합니다.

wget https://raw.githubusercontent.com/pinpoint-apm/pinpoint/master/hbase/scripts/hbase-create.hbase

 

스크립트 다운이 다 되셨으면 바로 스크립트를 실행해서 Pinpoint 테이블을 생성합니다.

hbase/bin/hbase shell ./hbase-create.hbase
성공 로그

여기까지 하셨으면 Hbase 구성은 끝납니다. 
다음으로 Collector와 Web을 설치해 보겠습니다.

 

 

 

 

3. Collector 설치

pinpoint 인스턴스 서버에서 Collector jar 파일을 다운로드합니다.

wget https://github.com/pinpoint-apm/pinpoint/releases/tag/v3.0.0/pinpoint-collector-3.0.0-exec.jar

 

해당 jar파일에 실행 권한을 줍니다.

chmod +x pinpoint-collector-3.0.0-exec.jar

 

그리고 바로 jar를 실행합니다.

nohup java -jar -Dpinpoint.zookeeper.address=localhost pinpoint-collector-3.0.0-exec.jar >/dev/null 2>&1 &
  • nohup ~ >/dev/null 2>&1 &
    • nohup.out 로그 파일 생성 없이, 세션 종료 없이 백그라운드 실행을 위해 사용합니다.
  • -Dpinpoint.zookeeper.address=localhost
    • 원래는 분산된 Hbase의 zookeeper 주소를 써야 하지만, 여기서는 다 같은 EC2 안에 있으니 localhost를 사용합니다.

Collector 설치가 끝났으니 바로 Web 설치를 진행하겠습니다.

 

 

 

 

4. Web 설치

Web설치는 Collector와 거의 동일합니다.
다운로드한 Jar 파일 주소만 다를 뿐이지 그 외에는 완전히 동일합니다.

wget https://github.com/pinpoint-apm/pinpoint/releases/tag/v3.0.0/pinpoint-web-3.0.0-exec.jar

 

jar 파일에 실행 권한을 주고 실행합니다.

chmod +x pinpoint-web-3.0.0-exec.jar
nohup java -jar -Dpinpoint.zookeeper.address=localhost pinpoint-web-3.0.0-exec.jar >/dev/null 2>&1 &

 

 

자 이제 한번 Pinpoint Web 띄워보겠습니다.
pinpoint 인스턴스의 퍼블릭 IPv4 주소로 접근하여 8080 포트로 실행시켜 보겠습니다.

정상적으로 Pinpoint Web 접근하게 되었습니다. 
Hbase, Collector, Web 설치는 모두 다 끝났으니, Agent 설치해 보겠습니다.

 

 

 

5. Agent 설치

Agent 인스턴스 서버에 접속하여 Pinpoint로 모니터링하고 싶은 프로젝트에 agent 설치합니다.

wget https://github.com/pinpoint-apm/pinpoint/releases/tag/v3.0.0/pinpoint-agent-3.0.0.tar.gz

 

다운로드한 압축파일을 압축 해제합니다.

tar xvzf pinpoint-agent-3.0.0.tar.gz

 

 

Agent가 Collector로 로그를 전송할 수 있도록 pinpoint 인스턴스 서버의 IP로 갈 수 있도록 설정 파일을 수정해야 합니다.
그리고 rate를 1로 수정합니다. rate는 얼마만큼 추적할 것인지에 대한 퍼센트(%)입니다. 
예를 들어 값을 10으로 하게 되면 1/10이 되어 10%만 샘플링하고, 1로 두게 되면 1/1이 되어 100% 추적이 됩니다.

# 이동
cd pinpoint-agent-3.0.0

# config 파일 수정
vi pinpoint-root.config

# ip와 rate 수정
profiler.transport.grpc.collector.ip=pinpoint ip로 변경
profiler.sampling.counting.sampling-rate=1

 

 

Pinpoint Agent를 Java 애플리케이션에 적용합니다.
적용하기 위해서 3가지 설정이 필수입니다.

-javaagent:/home/ubuntu/pinpoint/pinpoint-agent-3.0.0/pinpoint-bootstrap-3.0.0.jar 
-Dpinpoint.agentId=Pinpoint 에이전트의 ID 
-Dpinpoint.applicationName=모니터링할 애플리케이션의 이름
  • -javaagent
    • Pinpoint 에이전트의 경로를 지정합니다.
    • 이 에이전트가 애플리케이션의 동작을 추적하고 모니터링 데이터를 수집합니다.
  • -Dpinpoint.agentId
    • Pinpoint 에이전트의 ID를 설정하는 옵션입니다.
    • 이 ID는 고유한 에이전트 인스턴스를 식별하는 데 사용되며, 동일한 서버나 여러 서버에서 여러 에이전트를 구분할 수 있습니다.
  • -Dpinpoint.applicationName
    • 모니터링할 애플리케이션의 이름을 지정합니다.
    • Pinpoint UI에서 해당 애플리케이션을 구분하기 위해 사용됩니다.

nohup 명령어와 위에서 설정한 3가지 요소를 추가하여 Java 애플리케이션을 실행합니다.

nohup java -jar \
  -javaagent:/home/ubuntu/pinpoint/pinpoint-agent-3.0.0/pinpoint-bootstrap-3.0.0.jar \
  -Dpinpoint.agentId=prd-seolyu \
  -Dpinpoint.applicationName=prd-seolyuBack \
  $JAR_NAME > $REPOSITORY/nohup.out 2>&1 &

 

 

 

 

6. 모니터링 해보기

실행된 프로젝트에서 몇 가지 API와 페이지들을 호출해 보신 뒤, 
Pinpoint Web 서버로 브라우저 접속을 해보시면 아래와 같이 핀포인트에 요청들이 노출되는 것을 볼 수 있습니다.

 

 

우측 그래프의 점들을 드래그해서 확인해 보시면 각 요청들이 트레이스 되는 것도 보실 수 있습니다.

 

 

실패한 핑에 대해서 어떤 예외가 발생하여 실패하게 되었는지 트레이스로 확인할 수 있습니다.

 

 

5. Hbase 연결 타임아웃 오류


nGrinder 성능 테스트 툴을 통해서 동시 500건 요청을 하면 밑에 있는 오류가 발생하였습니다.

2024-10-03T05:14:24,885 WARN  [main-SendThread(127.0.0.1:2181)] zookeeper.ClientCnxn: Session 0x0 for server localhost/127.0.0.1:2181, Closing socket connection. Attempting reconnect except it is a SessionExpiredException.
java.net.ConnectException: Connection refused
	at sun.nio.ch.Net.pollConnect(Native Method) ~[?:?]
	at sun.nio.ch.Net.pollConnectNow(Net.java:672) ~[?:?]
	at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:946) ~[?:?]
	at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:344) ~[zookeeper-3.8.3.jar:3.8.3]
	at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1289) ~[zookeeper-3.8.3.jar:3.8.3]​

 이 오류는 HBase와 ZooKeeper 연관된 문제로, ZooKeeper 클라이언트가 127.0.0.1:2181 에 연결을 시도했으나 Connection refused 에러가 발생한 스택 트레이스입니다.

 

스택 트레이스를 보고 session 연결하는 timeout 시간을 늘리는 방법으로 진행해보았습니다.
기본 zookeeper.session.timeout 값을 40초 --> 90초 설정하였습니다.

// hbase/conf/hbase-site.xml
<property>
    <name>zookeeper.session.timeout</name>
    <value>90000</value>
</property>

 

하지만 계속해서 Connection refused 에러가 발생하였습니다...😪
평소에는 모니터링이 잘 운영되다가 성능 테스트할 때만 오류가 발생하길래 scale-up 해보았습니다.
기존 사양인 t3.small (2 vCPU, 2GB RAM) --> t3.medium (2 vCPU, 4GB RAM) 업그레이드 하였습니다.

 

동시 500건 요청했을 때 정상적으로 500건 모두 다 모니터링 되었습니다...!

이를 통해서, HBase와 ZooKeeper 사이에서 연결을 할 때 순간적으로 많은 요청을 하게 되면 에러가 발생하고
에러 발생 원인은 하드웨어 사양이 낮을수록 처리속도가 늦어지므로 에러가 발생하다는 것을 알게 되었습니다.

 


이번에는 동시 1000건 요청해보았습니다. 
하지만 다시 Connection refused 에러가 발생하였습니다...😪
다시 사양을 늘려서 t3.medium (2 vCPU, 4GB RAM) --> t3.large (2 vCPU, 8GB RAM) 진행보았습니다.

동시 1000건 요청이 정상적으로 모니터링 되었습니다...!

 

 

[출처]
Pinpoint APM Node 버전 설치하기  
[DevOps] Spring에 Pinpoint 적용하기  
Java - Pinpoint-Agent 로컬 구축