Skip to content

백엔드 서버 모니터링 및 로깅

임수빈 edited this page Aug 8, 2024 · 6 revisions

백엔드 서버 환경

image

백엔드 서버는 nginx 를 통해 80/443 포트를 이용해 EC2 내부에서 8080 포트에서 실행중인 Spring Boot에 요청을 전달하는 구조다. 이 환경에서 발생하는 로그나 여러 매트릭을 확인하기 위해 모니터링과 로깅 시스템을 구축하기로 결정했다.

모니터링 & 로깅 시스템 요구사항

  1. 다음 항목들을 모니터링 할 수 있어야 한다.
    • JVM 메모리 사용량
    • CPU 사용량
    • 커넥션, 스레드 풀 고갈
    • error 레벨 로그 증가량
    • 단위 시간 당 API 별 호출 횟수
    • API 별 응답 시간
  2. 로그를 시각화 대시보드에서 볼 수 있어야 한다.
  3. 모니터링 서버는 스프링 서버와 분리되어야 한다.
  4. 모니터링 및 로깅 정보는 외부에서 함부로 볼 수 없어야 한다.

요구사항을 만족하는 과정

모니터링 항목

우리가 모니터링하고자 하는 매트릭들은 모두 SpringBoot에서 발생하는 정보다. 따라서, Spring Boot에서 자신의 정보를 제공해야 한다. 이를 위해 Spring Boot Actuator를 사용하기로 했다. 아래 의존성을 Gradle에 추가했다. 공식 문서를 참고한다.

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-actuator'
	implementation 'io.micrometer:micrometer-registry-prometheus'
}

또한, Spring Boot Actuator가 제공하는 엔드포인트를 활성화하기 위해 다음 설정을 application.yml에 추가했다.

management:
  server:
    port: 8082
  endpoints:
    web:
      exposure:
        include: "prometheus,health"

모니터링 요구사항에서 외부에서 모니터링 정보를 접근할 수 없도록 해야 한다는 요구사항이 있었다. 이를 위해서 메트릭 정보를 제공하는 엔드포인트의 포트를 8082로 설정했다.

모니터링 서버 분리

스프링 부트 서버와 모니터링 서버는 분리되어있어야 안정적으로 모니터링을 할 수 있기 때문에 분리하기로 결정했다. 이를 도식으로 나타내면 다음과 같다.

image

두 서버는 같은 서브넷에 속하고, 보안 그룹 설정에서 같은 서브넷에 속한 경우 포트 제한 없이 통신할 수 있도록 되어있다. 이것이 Spring Boot Actuator가 8082 포트로 정보를 제공할 수 있는 이유다.

Spring Boot Actuator가 제공하는 메트릭을 주기적으로 수집하기 위해 프로메테우스를 사용하기로 결정했다. 자료도 많고, Spring Boot가 이를 위한 엔드포인트를 따로 제공해주는 점에서 신뢰도가 높다고 판단했기 때문이다. 시각화 도구로는 그라파나를 사용하기로 했고 이 역시 많은 자료가 있고, 프로메테우스 공식 문서에서 그라파나와의 통합을 내세우고 있기 때문이었다. 이를 도식화 하면 다음과 같다.

image

프로메테우스와 그라파나의 손쉬운 설치를 위해 도커와 도커 컴포스를 사용했다. 손쉽게 둘을 순차적으로 재시작하거나 다른 서버로 확장할 수 있기 때문이다. 도커 컴포스 설정의 예시를 모아둔 레퍼지토리를 참고해 구축했다. 정확한 설정은 보안상의 문제를 고려해 공개하지 않는다.

로그 저장소

모니터링과 로깅 시스템을 구축하는 시점에 아직 어떤 정보를 로그로 남길 것인지 정하는 정책이 불완전했다. 이는 기획 변경으로 인해 아직 기능 구현이 덜 되어있었기 때문이다. 따라서 지금 구축하는 로깅 시스템은 임시로 Spring Boot의 로그를 그라파나에서 볼 수 있도록 하는 것을 목표로 했다. 이를 위해 로키를 사용했다. 로키는 쉽게 말해 로그를 저장하는 것을 전문으로 하는 데이터베이스다. Spring Boot 웹 서비스에서는 기본적으로 LogBack을 이용해 로깅을 한다. 그리고 관련 설정을 따로 xml 로 작성하면, 그에 맞게 로그를 저장할 수 있다. 이 설정을 이용해 로그를 로그백에 저장하도록 설정했다. 아래는 설정 파일이다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <springProperty scope="context" name="appName" source="spring.application.name"/>

    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <pattern>
                %d{yyyy-MM-dd HH:mm:ss.SSS} | %t | %highlight(%-5p) | %cyan(%logger{36}) | %m%n
            </pattern>
        </encoder>
    </appender>

    <appender name="LOKI" class="com.github.loki4j.logback.Loki4jAppender">
        <http>
            <url>http://10.0.0.35:3100/loki/api/v1/push</url>
        </http>
        <format>
            <label>
                <pattern>app=${appName},host=${HOSTNAME},traceID=%X{traceId:-NONE},level=%level</pattern>
            </label>
            <message>
                <pattern>${FILE_LOG_PATTERN}</pattern>
            </message>
            <sortByTime>true</sortByTime>
        </format>
    </appender>

    <springProfile name="local">
        <root level="INFO">
            <appender-ref ref="Console"/>
        </root>

        <logger name="com.sb" level="DEBUG"/>
        <logger name="org.springframework.orm.jpa" level="DEBUG"/>
        <logger name="org.springframework.orm.transaction" level="DEBUG"/>
        <logger name="org.hibernate.orm.jdbc.bind" level="TRACE"/>
    </springProfile>

    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="LOKI"/>
        </root>
    </springProfile>

</configuration>

로키를 도입한 뒤 상황을 도식으로 나타내면 다음과 같다.

image

로깅 프레임워크

Logback 선택 이유

  1. Spring Boot와의 호환성:
    • Spring Boot에서 별도의 의존성 추가 없이 기본적으로 사용할 수 있어 설정과 관리가 간편합니다.
  2. 성능 비교:
    • 성능 면에서 Logback은 log4j2에 비해 다소 뒤처질 수 있지만, 프로젝트 초기 단계에서는 이러한 성능 차이가 크지 않을 것으로 예상됩니다.
  3. 러닝 커브:
    • Logback은 log4j2에 비해 레퍼런스가 많아 학습하기 쉬워 팀의 러닝 커브를 줄이고, 문제 해결 시 보다 신속한 대응을 가능하게 합니다.

모니터링 대시보드

Loki + Prometheus + Grafana 선택 이유

  1. 레퍼런스의 풍부함:
    • 이 조합은 많은 레퍼런스가 존재하여, 설정과 문제 해결 과정에서 도움이 되는 자료를 쉽게 찾을 수 있습니다.
  2. Loki: 로그 관리
    • 효율적인 인덱싱: Loki는 메타정보만 인덱싱하는 방식으로, 전체 내용을 인덱싱하는 Elasticsearch보다 더 간결하고 비용 효율적입니다.
    • Prometheus와의 통합: Loki는 Prometheus와 동일한 레이블을 사용해 메트릭과 로그의 원활한 전환이 가능합니다.
  3. Prometheus: 메트릭 관리
    • 시스템 성능 측정: Prometheus는 시스템 성능을 모니터링하고, 데이터 수집을 위한 퓨어 풀 모델을 사용합니다. 이 모델은 클라이언트의 부하를 줄이고, 네트워크 문제 발생 시에도 데이터 수집의 안정성을 유지합니다.
  4. Grafana: 시각화
    • 데이터 시각화: Grafana는 수집된 로그와 메트릭 데이터를 시각화하여, 시스템의 상태를 한눈에 파악할 수 있도록 지원합니다. 이는 문제 탐지와 대응을 신속하게 할 수 있게 합니다.
Clone this wiki locally