콘텐츠로 이동

2022 11 05

2022-11-05

Spring Actuator

  • 설명
    • 어플리케이션을 모니터링하고 관리하는 기능
    • Actuator는 HTTP와 JMX를 통해 확인이 가능함
    • 기능이 잘 돌아가는가? 지속적으로 모니터링, 서버를 재기동하거나 로그 정보를기 => 범어플리케이션 관점에서 처리해야 할 일이 많아
  • 주의점
    • 정보가 메모리에 올라가서 활용되기에 영구 저장을 위해서는 DB/file 저장 고려해볼 것
    • 시스템 조작할 수 있는 권한에 따라 접근제어를 철저하게 관리해야 함 => Spring Security와 같이 많이 이용
  • 사용법
    1. dependency 추가
    2. endpoint enable 설정
    3. endpoint 노출
  • 적용 플랜

    • Spring Boot Actuator + Micrometer Registry 의존성 추가
    • Spring Boot Actuator의 prometheus 엔드포인트 활성화
      • 서비스가 한 개 이상의 인스턴스로 이루어져 있다면, 서비스 구분을 위한 common tag 추가
    • Prometheus install & run
      • targets에 모니터링할 SpringBoot 어플리케이션 IP:Port 추가
      • prometheus.yml
        global:
          scrape_interval: "15s"
          evaluation_interval: "15s"
        scrape_configs:
        
        - job_name: "springboot"
          metrics_path: "/actuator/prometheus"
          static_configs:
        
          - targets:
            - "<my_spring_boot_app_ip>:<port>"
        - job_name: "prometheus"
          static_configs:
        
          - targets:
            - "localhost:9090"
        
    • Grafana install & run

Spring Actuator와 Springfox 충돌

  • 참고: https://middleearth.tistory.com/69
  • 문제상황
    • Swagger(Springfox) 와 Spring Actuator 충돌
    • Swagger : 모든 endpoint에 대해 documentation 해주는 역할
    • Actuator : 몇몇 endpoint를 직접 생성해서 노출시켜주는 역할
  • 원인
    • Springfox는 SpringMVC가 Ant-based path matcher를 기본값으로 경로를 찾음
    • Spring MVC 2.6.x 부터 Ant-based path matcher => Path Pattern-based matcher
  • 해결

    • ant_path_matcher로 변경
      spring.mvc.pathmatch.matching-strategy=ant_path_matcher
      
    • Swagger Endpoint 변경해서 쓰도록 설정
      @Bean
      public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, 
            ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, 
            EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, 
            WebEndpointProperties webEndpointProperties, Environment environment) {
          List<ExposableEndpoint<?>> allEndpoints = new ArrayList();
          Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
          allEndpoints.addAll(webEndpoints);
          allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
          allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
          String basePath = webEndpointProperties.getBasePath();
          EndpointMapping endpointMapping = new EndpointMapping(basePath);
          boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
          return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, 
            corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);
      }
      
      
      private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) {
          return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
      }