2022 11 05
2022-11-05¶
Spring Actuator¶
- 참고: https://docs.spring.io/spring-boot/docs/2.1.8.RELEASE/reference/html/production-ready-endpoints.html
- 참고: https://incheol-jung.gitbook.io/docs/study/srping-in-action-5th/chap-16
- 참고: https://sabarada.tistory.com/23
- 참고: https://meetup.toast.com/posts/237
- 개요
- 액추에이터는 스프링 부트 모니터링/메트릭과 같은 기능을 HTTP와 JMX 엔드포인트를 통해 제공
- 실행중인 스프링 부트 어플리케이션의 정보를 API 형식으로 확인할 수 있게 해주는 기능
- 실행중인 어플리케이션의 내부를 볼 수 있게 하고, 어느 정도 까지는 어플리케이션의 작동 방법을 제어할 수 있게 도움
- 어플리케이션 환경에서 사용할 수 있는 구성 속성들
- 어플리케이션에 포함된 다양한 패키지 로깅 레벨
- 어플리케이션이 사용중인 메모리
- 지정된 엔드포인트가 받은 요청 횟수
- 어플리케이션의 헬스체크
- 설명
- 어플리케이션을 모니터링하고 관리하는 기능
- Actuator는 HTTP와 JMX를 통해 확인이 가능함
- 기능이 잘 돌아가는가? 지속적으로 모니터링, 서버를 재기동하거나 로그 정보를기 => 범어플리케이션 관점에서 처리해야 할 일이 많아
- 주의점
- 정보가 메모리에 올라가서 활용되기에 영구 저장을 위해서는 DB/file 저장 고려해볼 것
- 시스템 조작할 수 있는 권한에 따라 접근제어를 철저하게 관리해야 함 => Spring Security와 같이 많이 이용
- 사용법
- dependency 추가
- endpoint enable 설정
- endpoint 노출
-
적용 플랜
- Spring Boot Actuator + Micrometer Registry 의존성 추가
- Spring Boot Actuator의 prometheus 엔드포인트 활성화
- 서비스가 한 개 이상의 인스턴스로 이루어져 있다면, 서비스 구분을 위한 common tag 추가
- Prometheus install & run
- targets에 모니터링할 SpringBoot 어플리케이션 IP:Port 추가
- prometheus.yml
- 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로 변경
- 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)); }