redis에 추가된 SUBSCRIBE, UNSUBSCRIBE 그리고 PUBLISH는 Publish/Subscribe 메시지 패러다임을 구현한 기능이다. sender(publisher)들은 특별한 receiver(subscriber)에게 값을 전달하는게 아니라 해당 채널에 메시지를 전달하면 그 메시지를 구독하고 있는 subscribe에게 메시지를 전송한다. subscribers는 하나 또는 그 이상의 채널에 구독을 요청하고 publisher가 누구인지 상관 없이 해당 채널에 들어온 모든 메시지를 읽게된다.

이 subscriber와 publisher의 decoupling은 확장성있는 성장을 가져올 수 있다.

 

Redis-Cli로 기능 사용하기


subscriber
redis-cli를 열고 SUBSCRIBE 채널1 채널2 ... 를 입력한다.

 

publisher
마찬가지로 redis-cli를 열고 PUBLISH 채널 메시지 를 입력해서 전송한다.

그럼 이를 구독하고 있던 subscriber 콘솔에 다음과 같이 출력된다.

 

Spring Boot 2.1.7에 적용하기


그럼 이 방식을 Spring boot에 적용하여 sub와 pub를 이용한 개발을 해보자.

우선 필요한 libaray는 다음과 같다.

spring-boot-starter-data-redis
spring-boot-starter-web
lettuce-core (기본적으로 탑재된 jedis보다 좋다고 하여 변경)
lombok
spring-boot-starter-test

 

라이브러리를 maven이나 gradle 통해 넣어주고 configuration을 통해서 지정해보다. 기본적으로 redisTemplate의 connection은 application.properties에 spring.redis.host, spring.redis.port에 지정해주면 그에 맞게 생성되기 때문에 별도로 설정해주지 않고 그대로 사용한다.

그리고 RedisSubscriber Listener를 구현해서 적용해주는데 RedisMessageListenerContainer를 설정해준다. 속성 값으로 MessageListenerAdapter를 부여해주는데 이 Adapter에는 MessageListener인터페이스를 구현하고 onMessage를 재정의하여 전달 받은 메시지에 대한 처리를 지정한다.

Configuration

    private RedisTemplate<String, String> redisTemplate;

    @Bean
    MessageListenerAdapter messageListener() {
        return new MessageListenerAdapter(new RedisMessageSubscriber());
    }

    @Bean
    RedisMessageListenerContainer redisContainer() {
        final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisTemplate.getConnectionFactory());
        container.addMessageListener(messageListener(), topic());
        return container;
    }

RedisMessageSubScriber

package com.study.redis.config;

import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * spring-boot-study
 *
 * @author wedul
 * @since 2019-08-21
 **/
@Service
public class RedisMessageSubscriber implements MessageListener {

    public static List<String> messageList = new ArrayList<>();

    @Override
    public void onMessage(final Message message, final byte[] pattern) {
        messageList.add(message.toString());
        System.out.println("Message received: " + new String(message.getBody()));

    }
}

그럼 기동해보고 redis-cli를 통해서 PUBLISH를 날려보면 위에 onMessage에 정의한 대로 콘솔로그가 찍히는지 보자.

그리고 Publisher도 설정하고 Test 코드를 작성하여 redis-cli처럼 결과가 나오는지 확인해보자.

우선 Publisher에서 사용되는 RedisMessagePublisher를 정의해준다.

Configuration

    @Bean
    RedisMessagePublisher redisPublisher() {
        return new RedisMessagePublisher(redisTemplate, topic());
    }

    @Bean
    ChannelTopic topic() {
        return new ChannelTopic("wedul");
    }

Test

package com.study.redis;

import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
@NoArgsConstructor
public class RedisApplicationTests {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Test
    public void contextLoads() {
        redisTemplate.convertAndSend("wedul", "No I'm genius");
    }

}

결과도 잘 나왔다. 굿굿 

ElasticCache를 사용하고 있다면 별도의 카프카와 같은 메시지큐 없이도 레디스를 사용해도 되지 않나 싶기도 하다.

 

자세한 코드는 여기에 redis 모듈 참고

https://github.com/weduls/spring5

 

weduls/spring5

study. Contribute to weduls/spring5 development by creating an account on GitHub.

github.com

 

혼자 공부를 집에서 어떻게 하면 효율적일까 고민을 많이했다.

집에서 주구장창 책을 읽고 해보면 스킬이 늘까? 그렇게 해봤지만 그게 정답은 아니었다. 남들에게는 모르겠으나 나에게는 아니었다. 

 

회사에서 하는 업무는 한정적이니 내가 회사에서 하지 못하지만 알고 싶고 잊고 싶지 않은 내용에 대해서 프로그램을 직접 만들면서 공부할 내용을 정리하고 싶었다.

그래서 만들게 된게 타임라인인데, 개발자 채용정보나 기술 블로그를 rss등을 사용해서 모아볼 수는 있으나 별도의 관리 툴이나 브라우저에서 확인해야해서 좀 불편했다. 그래서 그것을 한번에 볼수 있게 하는 사이트가 있으면 좋을 것 같아서 만들어봤다.

우선 주소는 http://wedul.space이다. aws에 도입하고 싶었으나 비용도 걱정되니해서 집에있는 간이 서버에 도입하였다.

화면은 잘 그릴지 몰라서 vue.js 책을 사서 간단하게 읽고 구성했다.

 

홈 / JOB / TECH로 페이지는 구성되어 있고 앞으로 로그인하여 본인이 구독하고 싶은 회사만 보는 기능을 추가할 예정이다. 그리고 자세히보기 누르면 현재는 해당 페이지로 이동하지만 timeline 내부에서 볼 수 있는 페이지를 추가할 예정이다.

 

원래는 혼자 저 정도 까지 구성하다가 크롤링 사이트를 확장하는데 혼자하기에는 조금 역부족이고 함께하고 하고자 하는 친구가 있어서 요청했다. 그래서 테크쪽과 프론트는 그 친구가 담당해주고 있다. 

저장소는 공개 되어있고 참여하고 싶으신 분들은 pull-request 보내주셔도 좋다.

https://github.com/weggdul/timeline

 

 

백엔드 구성


아무래도 나는 백엔드 개발자이다 보니 백엔드에만 사실 집중했다. 크롤링 양이 많지 않아서 별도 배치를 만들거나 큐에 쌓거나 할 필요는 없었으나 공부를 위해서 모두 구성해봤다.

우선 java8, spring-boot2.1.5로 구성되어 있고 멀티모듈로 관리하고 있다. (https://github.com/weggdul/timeline)

api 서버는 spring-batch를 통해 긁어온 데이터가 쌓여있는 mariadb에서 정보를 가져와 보여주며 중간에 redis가 위치해 있어 데이터를 캐시하고 있다.

 

batch 서버는 spring-batch에서 하루 두번 모든 JOB, tech사이트에 들러 크롤링해오고 그 정보를 kafka로 전송한다. kafka를 리스닝 하고 있다가 kafka에 데이터가 들어오면 읽어서 mariadb로 적재시키고 있다.

 

아직 미완 단계지만 다 만들어지고 나면 배포 자동 구성도 하고 seo도 달고 광고도 한번 달아봐야겠다.

공부도 확실히 되는거 같고.. 연말까지는 하고자 했던거 다 붙여보자.

  1. 지나가는개발자 2019.08.19 14:19

    토이프로젝트 깃 주소도 그렇고 서비스주소도 없다고뜨네요?

    • Favicon of https://wedul.site BlogIcon 위들 wedul 2019.08.19 14:26 신고

      안녕하세요. 주소 정보는 아래와 같구요. 다시한번 확인해주세요!

      서비스 사이트 : http://wedul.space
      github : https://github.com/weggdul/timeline

레오폴드 fc660c를 중고로 9만원에 구매하고 나서 1년정도 잘 사용했다. 하지만 사용하다보니 약간의 아쉬움이 있었다.

스프링 튀기는 소리가 꽤 크고 55g정도의 압력감으로 꽤 손목에 피로함을 느꼈다. 그러다 유튜브에서 fc660c 윤활제를 발라서 사용한 소리를 들었는데 너무 신세계였다.

그래서 윤활제를 바르기로 했다. 다른 분들은 흡음제도 집어넣고 러버덕 밑에 스프링에도 윤활제를 바르지만 나는 그렇게 까지 하지는 않고 단순하게 누르는 버튼에만 윤활제를 바르기로 했다.

 

윤활제 재료


일반 윤활제는 러버덕을 손상시킬 수 있어서 크라이톡스를 사용해야 하고 그 점성에 따라 103, 105, 107이 있다.

103과 107을 4:6정도로 사용한다고 하는데 나는 그 비율을 못 맞출 것 같아서 105를 주문해서 바르기로 했다. (난 전문가가 아니기 때문에 참고만 하시길..)

구매는 아래 사이트에서 했다. 

https://smartstore.naver.com/monstarkorea/products/3781850823?NaPm=ct%3Djzfmi0bk%7Cci%3D4afd550ad4d2018db61f3b4ae289f220637809ce%7Ctr%3Dsls%7Csn%3D426968%7Chk%3Dfbf2f1a47f4a49a846accf5f87c22b3341d883e6

 

윤활작업 전


윤활제를 바르기전에 소리는 아래 동영상처럼 꽤 소리가 거슬렸다.

https://www.youtube.com/watch?v=WtM78UbLhV8

 

윤활 과정


우선 윤활제 크라이톡스 105랑 면봉을 준비했다. 윤활제를 통에 넣고 바르기는 어려워서 종이컵을 준비해서 부어놓고 면봉에 뭍혀서 바르는게 좋다.

크라이톡스 105 윤활제

 

우선 키캡을 모두 벗겼다. 벗기고 나면 안에 먼지랑 이물질이 상당하다 ㅋㅋ 이걸 어떻게 썼길래 이렇게 더러운지 심각했다. ㅋㅋ 가볍게 청소했다.

 

그리고 카드를 이용해서 틈새를 벌리고 겉 테두리에 플라스틱을 벗겨냈다. 플라스틱을 벗겨내는 과정에서 밑판에 나사 하나를 풀어줘야 했다.

 

그리고 기판에 있는 선을 분리 했다. 생각보다 안빠져서 애먹었다. 선이 약해보여서 조심해야 할 것 같다.

 

각 나사들을 모두 제거하고 기판을 들어올리면 러버덕과 합쳐있는 기판이 분리된다. 이쪽에서 나는 러버덕을 건드리지 않기로 했다.

 

기판부분을 하나하나 분리하고 그 곳에 윤활제를 골고로 얇게 발라줬다.

그리고 다시 합체!

그런 다음 소리를 들어봤는데 엄청 신세계였다. 굿굿 잘한것 같다.

https://youtu.be/ipz4qv26OCQ

 

물론 나는 전문가가 아니라 유튜브 보고 해서 자세히 이 방법이 맞는지는 모른다. 그래도 내 키보드에서는 나에게 맞게 잘 윤활제가 뭍혀진 것 같다.

 

 

리액티브 또는 리액티브 스트림은 오늘날 spring framework에서 뜨거운 토픽으로 자리잡고 있다. 

그래서 나도 이전 포스팅에서도 정리도 하고 했었는데 아직 확실히 개념이 서질 않아서 다시 정리해봤다.

 

리액티브 스트림 (Reactive Stream) 이란?


리액티브 스트림은 무엇인가? 정확하게 공식문서에는 다음과 같이 기록되어 있다. (https://www.reactive-streams.org/)
Reactive Streams is an initiative to provide a standard for asynchronous stream processing with non-blocking back pressure.This encompasses efforts aimed at runtime environments (JVM and JavaScript) as well as network protocols.

이런 Reactive stream을 spring5에서 포함되었다.

  • Spring core framework는 Reactor와 RxJava를 통해 built-in 리액티브 프로그램을 할 수 있는 새로운 spring-flux 모듈을 추가하였다.
  • Spring security 5도 또한 reactive feature를 추가했다.
  • Spring Data umbrella project에서 Spring Data Commons에 새로운 ReactiveSortingRepository가 추가되었는데 가장먼저 redis, mongo, cassandra가 reactive에 지원한다. 불항하게도 일반적인 JDBC 드라이버의 블록킹 프로세스를 할 수 밖에 없는 디자인 때문에 Spring Data JPA는 이 특징에서 이점이 없다.
  • Spring Session또한 reactive feature를 추가하였고 2.0.0.M3qnxj SessionRepository내에 추가되었다.

 

Webflux 어플리케이션 만들기


스프링5를 통해서 reactive 프로그램을 만들어보면서 서비스를 확인해보자.

필요한 라이브러리
spring-boot-starter-parent
spring-webflux
jackson-databind
reactor-core
logback
lombok

데이터를 주고 받을 entity Post 객체

package com.study.webflex.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * spring-boot-study
 *
 * @author wedul
 * @since 2019-08-14
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Post {
    private int id;
    private String title;
    private String content;
}

 

데이터를 전달받을 Repository 클래스 DataRepository
- 우선 당장 데이터베이스를 선택하지 않고 이해를 먼저 돕기 위해서 가짜 데이터를 미리 static 블록을 이용해서 넣어놓자.

package com.study.webflex.dao;

import com.study.webflex.dto.Post;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * spring-boot-study
 *
 * @author wedul
 * @since 2019-08-14
 **/
@Repository
public class PostRepository {

  private static final Map<Integer, Post> DATA = new HashMap<>();
  private static int ID_COUNTER = 0;

  static {
    // initial data
    Arrays.asList("First Post", "Second Post")
      .stream()
      .forEach(title -> {
          int id = ID_COUNTER++;
          DATA.put(id, Post.builder().id(id).title(title).content("content of " + title).build());
        }
      );
  }

  Flux<Post> findAll() {
    return Flux.fromIterable(DATA.values());
  }

  Mono<Post> findById(Long id) {
    return Mono.just(DATA.get(id));
  }

  Mono<Post> createPost(Post post) {
    int id = ID_COUNTER++;
    post.setId(id);
    DATA.put(id, post);
    return Mono.just(post);
  }

}

WebFlux를 사용하기 위한 어노테이션 @EnableWebFlux와 @Configuration을 달아준다.


WebFluxApi
webFlux는 기존 mvc또한 지원하기 때문에 아래와 같이 Controller를 만들어 엔드포인트를 정의하여 사용할 수 있다. 내부에서는 HttpServletRequest, HttpServletResponse객체 대신 ServerHttpRequest와 ServerHttpResponse 객체로 동작한다.

package com.study.webflex.controller;

import com.study.webflex.dto.Post;
import com.study.webflex.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * spring-boot-study
 *
 * @author wedul
 * @since 2019-08-15
 **/
@RestController
@RequiredArgsConstructor
public class PostController {

  private final PostService postService;

  @GetMapping(value = "")
  public Flux<Post> all() {
    return postService.findAll();
  }

  @GetMapping(value = "/{id}")
  public Mono<Post> get(@PathVariable(value = "id") int id) {
    return postService.findById(id);
  }

  @PostMapping(value = "")
  public Mono<Post> create(Post post) {
    return postService.createPost(post);
  }

}

실행하면 원하는 데이터를 추출해서 볼 수있다.

webflux mvc로 출력된 결과

그리고 또다른 형태로도 사용할 수 있게 제공하는데 RouterFunction과 HandelrFunction을 정의해서 구현해야한다.

HandlerFunction은 http요청을 ServletRequest객체로 가져와서 Mono형태로 값을 반환하고 RouterFunction은 http요청을 HandlerFunction으로 다시 Mono의 형태로 라우팅해준다.

우선 요청을 받아서 작업을 진행할 Handler를 정의한다.

package com.study.webflex.handler;

import com.study.webflex.dto.Post;
import com.study.webflex.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

/**
 * spring-boot-study
 *
 * @author wedul
 * @since 2019-08-15
 **/
@Component
@RequiredArgsConstructor
public class PostHandler {

  private final PostService postService;

  public Mono<ServerResponse> all(ServerRequest serverRequest) {
    return ServerResponse.ok().body(postService.findAll(), Post.class);
  }

  public Mono<ServerResponse> get(ServerRequest serverRequest) {
    String id = serverRequest.path();
    return ServerResponse.ok().body(postService.findById(Integer.valueOf(id)), Post.class);
  }

  public Mono<ServerResponse> create(ServerRequest serverRequest) {
    return serverRequest.bodyToMono(Post.class).doOnNext(post -> postService.createPost(post)).then(ServerResponse.ok().build());
  }

}

그리고 RouterFunction을 정의하자 하나의 route를 정의하여 엔드포인트를 지정할 수 있고 추가적으로 andRoute를 통해 연속적으로 지정할수도 있다.

/** * spring-boot-study * * *@author *wedul * *@since *2019-08-15 **/@ComponentScan@EnableWebFlux@Configurationpublic class WebFluxConfig {

  @Bean  
  public RouterFunction<?> routes(PostHandler postHandler) {
    return RouterFunctions.route(GET("/route").and(accept(APPLICATION_JSON)), postHandler::all)
      .andRoute(GET("/route/{id}").and(accept(APPLICATION_JSON)), postHandler::get)
      .andRoute(GET("/route/create").and(accept(APPLICATION_JSON)), postHandler::create);  
    }
}

RouterFunction으로 나온 결과

동일하게 결과가 잘 나오는것을 확인할 수 있다.


그럼 여기서 왜, 그리고 언제 spring reactive를 사용하는게 좋은것일까? 아직까지는 위의 예제를 봐도 크게 어떤 부분 때문에 비동기, 논 블록킹을 스프링에서 사용하는지 언제 사용하는게 효율적인지 잘 모르겠다. 이게 나도 가장 궁금해서 이유를 찾아봤다.

일반적인 상황에서 쓰레드는 요청이 들어오면 끝날때까지 유지된다. 만약 데이터에 접근하고 기록하고 하는 작업이 있다면 이 작업들이 마무리 될 때까지 기다리고 있어야해서 쓰레드 낭비가 커진다.

그래서 응답은 바로 전달하는 non blocking에 비동기로 작업이 진행되도록 하는게 유리하다.
그런데 궁금한게 또 생겼다. 비동기-논블록킹으로 api를 만들면 비동기로 작업이 진행중인데 작업이 종료된 후 어떻게 client에서 결과를 가져올 수 있는건가?

바로 SSE (Server Sent Event) 개념을 이용하여 데이터가 전달된다. 예전에 spring 3.2 부터 추가 되었던 비동기 프로세스에 정리한적이 있었다. https://wedul.site/157

마찬가지로 spring5 reactor에서도 이 개념을 이용하여 동작한다.

우리가 spring webFlux를 사용할 때 내부적으로는 다양한 변화가 발생한다. reactor api에서 제공하는 publisher정보를 우리가 subscribe할 때 publisher는 client에게 각각의 아이템을 serialize하여 대량으로 전달한다.

이런 방식으로 우리는 많은 쓰레드를 생성하지 않고도 대기하고 있는 쓰레드를 이용하여 비동기적으로 데이터를 받을 수 있다. webflux에서 이런 로직을 사용하기 위해서 별도의 작업이 필요하지 않다. 알아서 지원해준다.

위에 정리했었다고 언급했던 spring mvc 3.2부터 추가된 AsyncResult, DefferedResult, Ssemiter등을 사용하면 webflux와 비슷하게 사용하는 것 같지만 사실은 내부적으로 Spring mvc는 스레드를 하나 생성하여 long polling 작업을 위해서 쓰레드를 대기하고 있기 때문에 비동기의 장점을 이용하기에는 어렵다.

실제로 예전 직장에서 long polling으로 client와 세션을 유지시키고 있을 때 대량의 사용자가 붙으면 설정했던 thread 개수를 초과해서 문제가 생긴 경험이 있다.

webFlux에서 이문제가 해결된다니 정말 좋은 것 같다. 왜 사용하는지 조금은 이해가 되는 것 같다.

그럼 말로만 하지말고 실제로 클라이언트에게 값을 전달을 해주는지 테스트해보자. 위에서 했던 소스는 데이터 양도 적고 값이 바로 나오기 때문에 정말 그렇게 나오는지 알 수가 없었다.

그럼 대기시간을 부여해서 확인해보자.


 

쓰레드 반환 후 결과값은 추후에 client에게 전달해주는지 테스트


우선 FouterFunction에 엔드포인트를 하나 더 추가하자.

@Bean
public RouterFunction<?> routes(PostHandler postHandler) {
  return RouterFunctions.route(GET("/route").and(accept(APPLICATION_JSON)), postHandler::all)
    .andRoute(GET("/route/{id}").and(accept(APPLICATION_JSON)), postHandler::get)
    .andRoute(GET("/route/create").and(accept(APPLICATION_JSON)), postHandler::create)
    .andRoute(GET("/delay/client").and(accept(APPLICATION_JSON)), postHandler::clientDelay);
}

그리고 delay기능을 추가하여 ServerResponse를 반환해보자.
만약 정상적인 결과라면 위에 println이 먼저 로그에 찍히고 클라이언트에서 데이터는 3초뒤에 나올 것 이다.

public Mono<ServerResponse> clientDelay(ServerRequest serverRequest) {
  Flux<Post> post = Flux.interval(Duration.ofSeconds(2))
    .take(3)
    .flatMap(number -> postService.findById(number.intValue()));

  System.out.println("test");
  return ServerResponse.ok().body(post, Post.class);
}

예상대로 로그는 먼저 찍힌다.

그리고 브라우저에서 결과는 예상대로 3초뒤에 출력되었다.


이제 정리가 되었다.

결론을 내리면 결과값을 기다릴 필요가 없이 비동기 논블록킹으로 동작하고 쓰레드를 반환하면 더 효율적인 운영이 가능할 것 같다. 그리고 webflux api를 사용할 경우에 걱정할 필요없이 값이 완료되면 클라이언트에게 전달되는 걸 확인 할 수 있었다.

비동기-논블록킹 프레임워크에서 중간에 블록킹이 걸리면 비효율적일 것 같다. 그래서 당장은 jdbc를 쓰는 경우에서는 쓰기 어렵겠지만 NoSql을 사용하는 경우에는 충분히 고려해볼만 할 것 같다.


공부에 사용한 저장소
https://github.com/weduls/spring5


출처 및 도움이 되었던 사이트
https://supawer0728.github.io/2018/03/11/Spring-request-model3/
https://techannotation.wordpress.com/2018/04/24/spring-reactive-a-real-use-case/
https://inyl.github.io/programming/2018/03/10/springboot2_api.html
https://stackabuse.com/spring-reactor-tutorial/
https://supawer0728.github.io/2018/03/15/spring-http-stereamings/

spring acturator를 통해서 스프링 애플리케이션의 작동여부등을 체크해보자.

 

설정


우선 gradle 라이브러리를 추가한다.

compile 'org.springframework.boot:spring-boot-starter-actuator'

그리고 기존에는 application.properties나 yml에 아래 옵션을 설정해줘야 했지만 기본적으로 설정이 되어있다.

endpoints.health.enabled=true

하지만 이는 Spring boot 2.0에서 다음으로 변경되었다. (https://stackoverflow.com/questions/48900892/how-to-enable-all-endpoints-in-actuator-spring-boot-2-0-0-rc1)

 

How to enable all endpoints in actuator (Spring Boot 2.0.0 RC1)

I moved to Spring Boot 2.0.0 RC1 from 1.5.10 and I am stuck with actuator in the latest version. How can I enable expose and enable all actuator endpoints? The only endpoints that get exposed are:...

stackoverflow.com

각 health, info등으로 적어도 되지만 귀찮으면 asterisk로 모두 포함해도 된다. 대표적인 엔드포인트에 대한 설명은 아래 기재해 놓았다.

management:
  endpoints:
    web:
      exposure:
        include: "*"

endpoint는 다음과 같이 지정해줄수 있다.

management:
  endpoints:
    web:
      base-path: /application

 

기본적인 정보를 보여주는 Endpoint 


Actuator에서 사용할 수 있는 기본적인 엔드포인트는 다음과 같고 더 자세하게 다른 정보를 볼 수 있는 api들도 제공한다.

 

/health

 앱의 대한 건강 정보를 보여준다. 


/info 

전체적인 앱에 대한 정보를 보여준다.


/metrics 

앱에 대한 통계정보를 보여준다. (카운터 등등) 

우선적으로 볼 수 있는 파라미터정보가 나오고 상세히 보고 싶은경우 다음 경로에 추가해서 조회하면 볼 수있다.


/httptrace

앱에 대한 상세 요청정보를 보여준다.

 

Spring Acturator의 데이터는 모두 휘발성으로 데이터를 저장하고 있지는 않다. 이를 저장하는 방법은 따로 있는지는 확인해보지는 않았다. 나주에 기회되면 확인해보고 정리해봐야겠다. 그리고 health endpoint를 내가 원하는대로 커스텀할 수 있다. 이 또한 당장 필요성이 없어 상세하게 알아보지는 않았지만 크게 어렵지는 않은 것 같다. 

모니터링 할 수 있는 Acturator가 생각보다 괜찮은 것 같다. 나중에 실무에서 써볼 수 있으면 써봐야겠다.

 

+ Recent posts