오늘은 Spring boot 2.0의
actuator
에 대해서 살펴보자. 아직 마일스톤 버전이라 바뀔 가능성은 있지만 크게 바뀌지 않을 것 같다. 기존(2.0 이전)의 actuator 와는 구조가 많이 변경되었다. 구조가 변경되었다고 하더라도 우리가 사용하는 것에 대해서는 많은 변화는 없다. 약간의 변화? 일단
spring-boot-actuator
모듈이 분리 되었다. 원래는 spring-boot-actuator 모듈 하나만 있었지만
autoconfigure
모듈이 새로 추가되었다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
하지만 우리는 기존과 동일하게
spring-boot-starter-actuator
만 디펜더시 받으면 된다. 그럼 자동으로
actuator
와
actuator-autoconfigure
이 디펜더시 받아진다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
일단 필자가 아는 것만큼 이야기를 해보자.
Endpoint
새로운
@Endpoint
어노테이션이 추가되었다. 기존에는 인터페이스로 되어있던 걸로 기억하는데 어노테이션으로 변경되었다. 새로운 @Endpoint 속성에는 세가지 속성이 있다.
id
,
exposure
,
defaultEnablement
속성인데 id는 말그대로 id를 뜻하며 endpoint 도 id와 동일하게 지정된다. exposure 은 노출 속성을 의미한다. 두가지 속성이 있는데
JMX
와
WEB
이 있다. 아무 설정하지 않았을 경우에는 모두 다 노출되며 특정한(JMX 혹은 WEB) 경우에 노출 시키고 싶다면 JMX 또는 WEB을 지정해주면 된다. defaultEnablement 속성은 기본적으로 enable 시킬 것인가 아니면 disable 시킬것인가 속성이다.
일단 한번 코드로 살펴보자.
@Endpoint(id = "hello")
@Component
public class HelloEndpoint {
@ReadOperation
public String hello(String name) {
return "hello " + name;
}
@WriteOperation
public String foo(String name) {
return name;
}
}
나머지는 위에서 설명을 했으니 넘어가고 여기서 조금 익숙하지 않은 어노테이션이 눈에 띈다.
@ReadOperation
,
@WriteOperation
어노테이션이다.
이 어노테이션은 말그대로 읽기 오퍼레이션이냐 쓰기 오퍼레이션이냐를 정하는 것이다. 그럼 무엇이 다를까?
ReadOperation
은 http method의 GET에 해당하고
WriteOperation
어노테이션은 POST에 해당한다. 이외에도
@DeleteOperation
어노테이션도 존재한다. 아마도 DELETE 메서드에 해당하지 않을까 생각된다. 아직 테스트는 해보지 않았지만 그러지 않을까?
한번 요청을 해보자.
http http://localhost:8080/application/hello name==wonwoo
hello wonwoo
위와 같이 요청을 했을 경우 hello wonwoo를 볼 수 있을 것이다. 아니다 볼 수 없다. 왜냐하면 기본적으로 몇가지를 제외하고는 모두 disable 되어 있기 때문이다. 루트와
info
,
status
를 제외하고는 모두 비활성화 되어있다. enable 시키기 위해서는 프로퍼티에 다음과 같이 작성하면 된다.
endpoints.hello.web.enabled=true
만약 web을 활성화 시키고 싶다면 위와 같이 작성하면 된다. JMX를 활성화 시키고 싶다면 동일하게 endpoints.hello.jmx.enabled=true 를 작성해주면 된다. 하지만 지금 버그인지 원래그런건지 아니면 필자가 M5 버전이라 그런건지 web만 설정하고 싶어서 저렇게 했는데 jmx도 보인다. 하지만 jmx만 설정하면 web은 동작하지 않는다. 뭐 나중에 다시 확인해봐서 안되면 한번 물어나보지 머..
위와 같이 작성을 했다면 다시 요청을 해보자. 그럼 원하는 대로 hello wonwoo를 볼수 있을 것이다.
하지만 spring boot 에서는 web을 사용할 때 다른 것을 권장하고 있다.
@WebEndpointExtension
어노테이션을 사용해서 웹에 특화되게 확장한 어노테이션이라고 생각하면 된다. 다른 건없다. 사용법도 간단하다. 아래와 같이 해당 엔드포인트만 연결해주면 된다.
@WebEndpointExtension(endpoint = HelloEndpoint.class)
@Component
public class HelloWebEndpointExtension {
private final HelloEndpoint delegate;
public HelloWebEndpointExtension(HelloEndpoint delegate) {
this.delegate = delegate;
}
@ReadOperation
public WebEndpointResponse<String> hello(@Nullable String name) {
return new WebEndpointResponse<>(delegate.hello(name));
}
}
어렵지 않다. 딱 보기에도 쉽다. 참고로 spring5부터는 Nullable을 지원한다. 옵션값일 경우 spring 에서 제공해주는 Nullable 어노테이션을 사용하면 된다. DI를 받을 때에도 옵션 값이면 Nullable을 사용하면 된다.
private final SomeClass some;
public HelloEndpoint(@Nullable SomeClass some) {
this.some = some;
}
그리고 Spring boot 만의 Conditional 어노테이션인
ConditionalOnEnabledEndpoint
어노테이션이 추가 되었다. 이것은
endpoints.hello.enabled=false
일 때는 빈으로 동작 시키지 않는 어노테이션이다.
@Bean
@ConditionalOnEnabledEndpoint
public HelloEndpoint helloEndpoint() {
return new HelloEndpoint();
}
위와 같이 설정 했을 경우
endpoints.hello.enabled=false
이라면
helloEndpoint
는 빈으로 등록 시키지 않는다. 이외에도
ConditionalOnEnabledHealthIndicator
어노테이션도 추가 되었다.
HealthIndicator
는 설정 하는 것 이외에는 변경된 부분은 없다. 기존과 동일하게
HealthIndicator
인터페이스 혹은
AbstractHealthIndicator
추상 클래스를 구현하면 된다.
@Component
public class DummyHealthIndicator implements HealthIndicator {
@Override
public Health health() {
return Health.up().build();
}
}
HealthIndicator는 우리가 사용하는 것에 대한 변화는 없으므로 넘어가고 마지막으로 Endpoint에 새로 추가된 어노테이션이 하나 더 있다. 그건
@Selector
라는 어노테이션인데 간단히 말해서
PathVariable
어노테이션과 동일하다.
@ReadOperation
public WebEndpointResponse<String> selector(@Selector String name) {
return new WebEndpointResponse<>(delegate.hello(name));
}
위와 같이 설정 했을 경우에 다음과 같이 요청이 가능하다.
http http://localhost:8080/application/hello/wonwoo
hello wonwoo
그럼 동일하게
hello wonwoo
라고 응답 받을 수 있다.
안타깝게 현재는 Post로 받을때 바디를 Object로 받을 수 는 없다. 나중에 가능할지는 모르겠지만 현재로는 String, Integer, Long 기타 enum 등으로만 받을 수 있다.
@WriteOperation
public WebEndpointResponse<Person> person(String name) {
return new WebEndpointResponse<>(new Person(delegate.hello(name)));
}
위와 같이 POST로 설정했을 경우 body로 요청 할 수 있다.
http POST http://localhost:8080/application/hello name=wonwoo
{
"name": "hello wonwoo"
}
이렇게 actuator 의 Endpoint에 변화에 대해서 알아봤다. 다른 것들은 우리가 사용하는데 있어서 많은 변화는 없었지만 내부적으로 많은 변화가 있었다. 특히 reactive가 추가 됨으로써 구조적으로 많은 변화가 있었다. 우리는 잘 가져다 쓰면 된다. 물론 내부를 아는 것이 휠씬 좋지만 일단 먼저 어떻게 사용하지는 아는 것도 중요하니 잘 가져다 쓰자.
오늘은 이렇게 Spring boot 2.0 actuator에 대해서 살펴봤다. reactive stream 도 공부하는 중이라 조만간 한번 언급을 할 예정이다. 하지만 너무 어렵..