2024.07.13 - [Spring/대용량 트래픽] - Spring MVC vs Webflux 성능 비교(with Jmeter)
여러가지 테스트로 Webflux가 대규모 트래픽환경에서 매우 효율적으로 동작하는것을 확인했다.
그렇다면 비동기 방식으로 제대로 작동하고 있다는것은 어떻게 확인할수 있을까?
Blockhound
비동기 프로그래밍의 경우 동기 프로그래밍 대비 디버깅하기 어렵다.
개발과정에서 디버깅을 도와주는 도구가 바로 Blockhound이다. Java agent라고 볼수있다.
- Non-blocking Thread 환경에서 blocking 되는 조건을 찾아주는 도구이다.
설정
- Gradle
- Implementation 'io.projectreactor.tools:blockhound:$LATEST_RELEASE'
- testImplementation 'io.projectreactor.tools:blockhound:$LATEST_RELEASE'
- Code
- Blockhound.install() : 이 메서드 호출 다음부터 코드 검출을 진행한다.
- JDK 13이후 버전 -> JVM 옵션을 추가해줘야 함
- -XX:+AllowRedefinitionToAddDeleteMethods
build.gradle
implementation 'io.projectreactor.tools:blockhound:1.0.8.RELEASE'
WebfluxApplication.java
@SpringBootApplication
public class WebfluxApplication {
public static void main(String[] args) {
BlockHound.install();
SpringApplication.run(WebfluxApplication.class, args);
}
}
어플리케이션 실행 이전에 blockhound를 실행해서 모든 코드에 대해 검출 진행
오류코드 검출 예시
@SpringBootApplication
public class WebfluxApplication implements ApplicationRunner {
public static void main(String[] args) {
BlockHound.install();
SpringApplication.run(WebfluxApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception {
Mono.delay(Duration.ofSeconds(1))
.doOnNext(it ->{
try {
Thread.sleep(100); // blocking에 해당
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
})
.subscribe();
}
}
테스트 환경에서 활용
build.gradle
testImplementation 'io.projectreactor.tools:blockhound:1.0.8.RELEASE'
tasks.withType(Test).all{
if(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_13)){
jvmArgs += [
"-XX:+AllowRedefinitionToAddDeleteMethods"
]
}
}
UserControllerTest.java
@WebFluxTest(UserController.class)
@AutoConfigureWebTestClient
class UserControllerTest {
static {
BlockHound.install();
}
@Autowired
private WebTestClient webTestClient;
@MockBean
private UserService userService;
@MockBean
private PostServiceV2 postServiceV2;
@Test
void blockHound(){
StepVerifier.create(Mono.delay(Duration.ofSeconds(1))
.doOnNext(it -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}))
.verifyComplete();
}
구현 로직상 blocking이 필요한 부분이 있으면 그 부분은 blocking으로 처리해줘야하는데, blockhound는 이 부분까지 잡을수 있다 어떻게 해야 원하는 부분만 blocking할수 있을까?
static {
BlockHound.install(
builder -> builder.allowBlockingCallsInside(클래스 경로, 메서드이름)
);
}
install() 메서드의 인자로 위와같이 설정할수 있다.
2024.07.20 - [Spring/대용량 트래픽] - Spring Webflux와 Redis이용해서 접속자 대기열 시스템 만들기(1)
'Spring > 대용량 트래픽' 카테고리의 다른 글
Spring Webflux와 Redis이용해서 접속자 대기열 시스템 만들기(2) (1) | 2024.07.23 |
---|---|
Spring Webflux와 Redis이용해서 접속자 대기열 시스템 만들기(1) (0) | 2024.07.20 |
Spring MVC vs Webflux 성능 비교(with Jmeter) (0) | 2024.07.13 |
Reactive Redis 사용법 (1) | 2024.07.12 |
Reactive Redis란? (0) | 2024.07.07 |