Spring Framework

Spring Webflux - Utils

흥부가귀막혀 2022. 3. 14. 13:14

BlockHound

  • Spring Webflux 는 예상치 못한 blocking 로직이 있을 경우 성능에 큰 영향을 미치기 때문에 이러한 로직이 있는지 탐지하고 수정할 수 있어야 한다.
  • BlockHound 는 비지니스 로직이 수행될 때 blocking 로직이 있으면 exception 을 던져 blocking 로직을 파악할 수 있게 도와준다.
  • 번역 gateway 에서는 아래와 같은 방식으로 blockhound 를 실행한다.

Dependency 추가

 <dependency>
     <groupId>io.projectreactor.tools</groupId>
     <artifactId>blockhound</artifactId>
     <version>1.0.3.RELEASE</version>
 </dependency>

Application class 에서 BlockHound 실행여부를 판단

@SpringBootApplication
public class Application {
    static final String BLOCK_HOUND_INSTALL = "service.block-hound.install"; // (1)

    public static void main(String[] args) {
        boolean installBlockHound = SpringApplication.run(Application.class, args) // (2)
            .getEnvironment()
            .getProperty(BLOCK_HOUND_INSTALL, boolean.class, false);

        if (installBlockHound) {
            BlockHound.install(); // (3)
        }
    }
}

(1) application 실행시 특정 config 값을 통해 BlockHound 실행 여부를 판단할 수 있게 정의한다.
(2) application 실행시 BlockHound 실행 여부를 판단할 수 있는 config 값을 조회한다.
(3) BlockHound 를 실행하도록 config 가 주입되었으면 install API 호출을 통해 실행

  • 비지니스 로직 수행중에 blocking 로직이 탐지되면 아래와 같이 에러가 발생한다.
java.lang.Error: Blocking call! java.lang.Thread.sleep
at reactor.blockhound.BlockHound$Builder.lambda$new$0(BlockHound.java:167)
at reactor.blockhound.BlockHound$Builder.lambda$install$6(BlockHound.java:226)
at reactor.blockhound.BlockHoundRuntime.checkBlocking(BlockHoundRuntime.java:46)
at java.lang.Thread.sleep(Thread.java)
at com.example.demo.DemoApplication.block(DemoApplication.java:30)

Reloadable Configuration

  • Reloadable Configuration 을 하는 방법은 몇가지 있지만 Spring 에서 공식적으로 지원하는 방식은 Spring Cloud에서 지원하는 @RefreshScope 사용한 방식이다.

Spring Cloud 에 대한 dependency 추가

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter</artifactId>
    </dependency>
</dependencies>

Reloadable ConfigurationProperties 정의

	@Bean
	@RefreshScope
	@ConfigurationProperties(prefix = "example.reload.properties")
	public Map<String, String> exampleProperties() {
		return new HashMap<String, String>();
	}

Configuration 이 필요한 곳에서는 Bean 으로 등록된 Properties 를 주입받아 사용.

@Autowired
private Map<String, String> exampleProperties;

/**
 * properties value 조회
 */
public String getValue(String key) {
   return exampleProperties.get(key);
}

Configuration 변경이 필요할 경우 config file 을 수정한 뒤 다음과 같이 actuator API 호출. (단, management.endpoints.web.exposure.include 에 refresh 가 활성화 되있어야 한다.)

curl -XPOST http://{host}:{port}/actuator/refresh