오늘은 오랜만에 Spring 이야기를 한다. 맨날 원칙원칙 하는 이야기만 했으니 오늘은 쉬어가는 타임으로 재미있는(?)걸 해보도록 하자. 그 중에 오늘은 Spring boot 프로젝트 중에 Actuator 프로젝트가 있다. 이것은 애플리케이션 내부를 볼 수 있게 하는 아주 재밌는 기능이다. Spring의 컨텍스트 빈, 자동설정, 환경설정, 매트릭 정보를 볼 수 있는 아주 유용한 프로젝트이다. 이 포스팅은 Spring boot 1.5 버전의 Actuator롤 소개한다. 이전 버전에서는 조금 다를 수 있으니 참고하면 되겠다.
Actuator Endpoints
일단 Actuator 엔드 포인트를 살펴보도록 하자.
ID |
Description |
actuator |
HATEOAS가 classpath에 있으면 해당하는 정보들을 보여준다. |
auditevents |
현재 어플리케이션의 인증 등을 이벤트로 감지해서 보여준다. |
autoconfig |
어떤 자동설정 조건이 통과하고 실패했는지 보여준다. |
beans |
어플리케이션의 빈 정보들을 보여준다. |
configprops |
해당 프로퍼티의 빈이 어떻게 주입되어 있는지 보여준다. |
dump |
스레드 활동의 덤프를 보여준다. |
env |
환경 프로퍼티를 보여준다. |
flyway |
flyway의 마이그레이션 정보를 보여준다. |
health |
어플리케이션의 상태 정보를 보여준다. |
info |
어플리케이션의 정보를 보여준다 |
loggers |
어플리케이션의 로그 설정 정보를 보여준다. |
liquibase |
Liquibased의 마이그레이션 정보를 보여준다. |
metrics |
메모리, 클래스 로더, http 요청횟수, 마지막 요청의 걸린 시간 등 매트릭 정보를 보여준다. |
mappings |
URI 경로와 해당 경로를 포함한 컨트롤러의 매핑 정보를 보여준다. |
shutdown |
어플리케이션을 종료한다. (이건 켜놓는건 위험하다. 만약 정말로 하고 싶다면 권한을 ADMIN으로 하길 권장한다.) |
trace |
http의 요청의 대한 정보(method, headers, response)를 보여준다. |
일단 Actuator 정보는 위와 같다. 그리고 Spring mvc를 사용하면 추가로 다음과 같은 endpoints를 사용할 수 있다.
ID |
Description |
docs |
spring-boot-actuator-docs 를 추가하면 Actuator의 endpoints의 문서로 확인 할 수 있다. |
heapdump |
heap dump 를 압축해서 다운로드 한다. |
jolokia |
Jolokia 를 사용할 경우 HTTP를 통해 JMX를 확인할 수 있다. |
logfile |
logfile의 내용을 확인 할 수 있다. |
아주 다양한 정보를
Actuator
를 통해 확인할 수 있다. 위의
ID
는 해당 하는 endpoints이다. 일단 1.5에서는 기본적으로 시큐리티를 사용하지 않아도 인증처리를 해야 한다. 이전에는 인증처리 없이 바로 사용할 수 있었는데 1.5 이후에는 몇 가지의 endpoints를 제외한 나머지는 모두 인증을 해야 한다.
health
,
info
,
docs
을 제외한 나머지들은 인증을 해야 하지만 만약 그러고 싶지 않다면 프로퍼티에 아래와 같이 설정하면 된다.
management.security.enabled=false
만약의 특정한 endpoints를 인증 처리 없이 개방하고 싶다면 다음과 같이 하면 된다.
endpoints.beans.sensitive=false
위는
beans
endpoint의 인증처리를 하지 않겠다는 의미이다. 이렇게 하면
beans
은 인증 처리 없이 바로 확인 할 수 있다. 형식은 endpoints.{ID}.sensitive 로 작성하면 된다. 또한 만약 해당 endpoints 를 사용하고 싶지 않다면 아래와 같이 작성 하면 된다.
endpoints.beans.enabled=false
보통은 위와 같은 정보들은 외부에 노출 시킬 필요는 없다. 인증이 있다 한들 굳이 노출 시킬 필요는 없는 정보들이다. 그래서 해당하는 포트와 context-path를 변경할 수 있는데 다음과 같이 작성하면 된다.
management.context-path=/application
management.port=9090
실제로 spring boot 2.0부터는 기본값으로
context-path
가
/application
으로 되어있다. 아직 M2 버전이기에 바뀔 가능성도 있지만 그럴 확률은 적어 보인다. 아무튼 참고하면 되겠다.
설정
일단 사용해 보도록 하자. 각자가 프로젝트를 만들고 (STS, IDEA)등 혹은 http://start.spring.io 에서
Actuator
를 선택 혹은 아래와같이 maven(기준)에 디펜더시를 추가하도록 하자.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
일단
actuator
는 web과 종속적이지 않아 web도 추가하였다. 그리고 나서 바로 실행시켜도 된다. 서버를 띄우고 확인해보도록 하자. 예제이니 필자의 경우에는 아래와 같이 인증은 하지 않고 포트 변경 및 context-path만 변경하였다.
management.context-path=/application
management.port=9090
management.security.enabled=false
위와 같이 설정했다면 이제 사용해보도록 할껀데 다 살펴보긴엔 양도 많고 한번씩 해보면 될 듯 싶으니 몇가지만 확인해보도록 하자. 필자는 httpie를 사용해서 curl로 하지 않았다. (모르는 사람을 위해..)
Beans
http localhost:9090/application/beans
[
{
"context": "application",:
"parent": null,
"beans": [
{
"bean": "springBootActuatorExampleApplication",
"aliases": [],
"scope": "singleton",
"type": "me.wonwoo.SpringBootActuatorExampleApplication$$EnhancerBySpringCGLIB$$824ab5a8",
"resource": "null",
"dependencies": [
"counterService",
"org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@12405818"
]
},
{
"bean": "org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory",
"aliases": [],
"scope": "singleton",
"type": "org.springframework.core.type.classreading.CachingMetadataReaderFactory",
"resource": "null",
"dependencies": []
}
]
},
...
]
Spring이 관리하는 bean들의 정보들이다. 물론 아주 많지만 아주 많기에 생략했으니 참고하면 되겠다.
* bean: 스프링에서 관리하는 빈 이름 또는 ID 이다.
* aliases: 해당 빈의 alias 정보이다. 근데 어노테이션으로 alias를 어떻게 주는 거지?..
* scope: 해당 빈의 스코프 정보이다.
* type: 해당 빈의 타입이다.
* resource: 해당 .class 파일 위치의 대한 정보이다.
* dependencies: 해당 빈의 주입된 빈 ID 정보들이다.
health
어플리케이션의 상태를 모니터링 할 수 있는
/health
endpoint이다. 여기에는 실제디스크 공간과 상태, 만약 db까지 연결된 상태라면 db 상태도 JSON으로 출력 된다. 이 외에도 JMS, Mail, Mongo, Redis 기타 등등 여러가지의 상태 체크를 할 수 있다.
http localhost:9090/application/health
{
"diskSpace": {
"free": 67516727296,
"status": "UP",
"threshold": 10485760,
"total": 120137318400
},
"status": "UP"
}
info
어플리케이션의 정보를 확인할 수 있다. 아무 설정 하지 않았다면 정보가 없겠지만 프로퍼티에 아래와 같이 작성하면 해당정보가 출력된다.
info.app.encoding=@project.build.sourceEncoding@
info.app.java.source=@java.version@
info.app.java.target=@java.version@
project.artifactId: actuator-example
project.name: spring-boot-actuator-example
project.description: my spring boot actuator example
info.build.artifact=${project.artifactId}
info.build.name: ${project.name}
info.build.description: ${project.description}
info.spring.profiles: ${spring.profiles.active:default}
info.*
을 사용하면 된다. 그러면 info 호출시 아래와 같이 출력된다.
http localhost:9090/application/info
{
"app": {
"encoding": "UTF-8",
"java": {
"source": "1.8.0_121",
"target": "1.8.0_121"
}
},
"build": {
"artifact": "actuator-example",
"description": "my spring boot actuator example",
"name": "spring-boot-actuator-example"
},
"spring": {
"profiles": "default"
}
}
metrics
아마 모니터링하면 가장 많이 봐야 할 것이 metrics 정보들이다. 여기에는 메모리 정보 http 요청횟수, 마지막 요청의 걸린 시간등 모니터링에 필요한 정보들을 보여준다.
http localhost:9090/application/metrics
{
"classes": 6773,
"classes.loaded": 6773,
"classes.unloaded": 0,
"gc.ps_marksweep.count": 2,
"gc.ps_marksweep.time": 194,
"gc.ps_scavenge.count": 11,
"gc.ps_scavenge.time": 158,
"heap": 1864192,
"heap.committed": 267264,
"heap.init": 131072,
"heap.used": 43373,
"httpsessions.active": 0,
"httpsessions.max": -1,
"instance.uptime": 3193236,
"mem": 319540,
"mem.free": 223890,
"nonheap": 0,
"nonheap.committed": 53224,
"nonheap.init": 2496,
"nonheap.used": 52277,
"processors": 4,
"systemload.average": 1.8515625,
"threads": 39,
"threads.daemon": 36,
"threads.peak": 43,
"threads.totalStarted": 46,
"uptime": 1749857
}
아주 유용한 정보들이 많이 출력된다.
trace
아마
metrics
다음에 가장 많이 본다면 그것은
trace
일 듯하다. trace을 더 많이 볼려나. http 요청의 대한 정보들이 출력된다.
http localhost:9090/application/trace
[
{
"info": {
"headers": {
"request": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"accept-encoding": "gzip, deflate, br",
"accept-language": "ko-KR,ko;q=0.8,en-US;q=0.6,en;q=0.4",
"connection": "keep-alive",
"cookie": "Idea-c1fe11da=c59f8ecf-0dc5-414f-9dda-0fa38e6c3ab2; _ga=GA1.1.317427494.1491117853",
"host": "localhost:8080",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"
},
"response": {
"Cache-Control": "no-cache, no-store, max-age=0, must-revalidate",
"Content-Length": "5",
"Content-Type": "text/html;charset=UTF-8",
"Date": "Wed, 28 Jun 2017 14:23:23 GMT",
"Expires": "0",
"Pragma": "no-cache",
"Strict-Transport-Security": "max-age=31536000 ; includeSubDomains",
"X-Application-Context": "application",
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"X-XSS-Protection": "1; mode=block",
"status": "200"
}
},
"method": "GET",
"path": "/",
"timeTaken": "9"
},
"timestamp": 1498659803318
}
]
하지만 이것은 메모리에 저장된다. 그러므로 서버가 다운되면 모든 데이터는 사라진다. 개발때는 문제 없겠지만 만약 운영서버에 메모리를 사용한다면 일회성 밖에 되지 않는다. 또한 default로 100개 까지만 저장되고 그 이후의 데이터는 사라진다. 100개보다 더 많이 설정은 할 수 있지만 요청이 많은 곳이라면 1000개든 10000개든 소용없을 것이다. 그렇다고 마냥 메모리도 늘릴수도 없을 것이다. 좀 더 영구적이며 많이 넣을 수 있는 곳에 데이터를 저장해야 된다. 그렇다고 RDB에 넣는건 뭔가 손해 인 듯하고.. 다음 시간이나 다다음시간에 영구적으로 넣을 수 있도록 redis나 mongodb 혹은 다른 nosql에 넣어보도록 하자.(일단 개발부터 해야되니..)
일단 오늘은 여기까지하고 다음시간(양이많으면 3편에 걸쳐..)에 좀 더 알아보도록 하고 오늘은 Spring의 Actuator 프로젝트를 소개 정도만 했다. 이정도만 알아도 개발에 사용하는데에는 문제가 없을 것(?) 같다. 좀 더 endpoints에 대한 내용은 많지만 어렵지 않으니 각자가 한번씩 어떠한 정보를 보여주는지 확인해보도록 하자.