본문으로 바로가기
728x90
반응형
SMALL

API 호출 성능테스트를 진행하였다

 

1. 테스트 준비

공통조건: 외부로 요청하는 get api url은 동일하다.

 

1.Spring Mvc + RestTemplate

@Bean
public RestTemplate restTemplate(){
    return new RestTemplate();
}

@Slf4j
@RequiredArgsConstructor
@Service
public class ApiCallService {

    private final RestTemplate restTemplate;

    @Value("${rest.fpl.date.url}")
    private String testUrl;

    public ResponseEntity<String> fpl_date_call_v2(){
        log.info(Thread.currentThread().getName());
        return restTemplate.getForEntity(testUrl,String.class);
    }
}

@RequiredArgsConstructor
@RestController
public class BlockApi {

    private final ApiCallService nonBlockService;

    @GetMapping("/v2")
    public ResponseEntity<String> test2(){
        return nonBlockService.fpl_date_call_v2();
    }

}

 

2.Spring webFlux + WebClient

@Bean
public WebClient webClient() {
    return WebClient.create();
}

@Slf4j
@RequiredArgsConstructor
@Service
public class ApiCallService {

    private final WebClient webClient;


    @Value("${rest.fpl.date.url}")
    private String testUrl;
    
    public Mono<String> fpl_date_call_v1(){
        log.info(Thread.currentThread().getName());
        return webClient
                .get()
                .uri(testUrl)
                .retrieve()
                .bodyToMono(String.class);
    }

}

@RequiredArgsConstructor
@RestController
public class NonblockApi {
    private final ApiCallService blockService;


    @GetMapping("/v1")
    public Mono<String> test1(){
        return blockService.fpl_date_call_v1();
    }
}

 

 

2.테스트 결과

NonBlock

에러메시지

reactor.netty.internal.shaded.reactor.pool.PoolAcquirePendingLimitException: Pending acquire queue has reached its maximum size of 1000
...

reactor.netty.http.client.PrematureCloseException: Connection prematurely closed DURING response
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ Body from GET http://127.0.0.1:10118/ffice/20240305 [DefaultClientResponse]
    *__checkpoint ⇢ Body from GET http://127.0.0.1:10118/ffice/20240305 [DefaultClientResponse]
Original Stack Trace:
평군 에러율: 279304/697487 = 40%

평균 TPS: 2375


Block

에러메시지

2024-04-03T17:42:23.351+09:00 ERROR 53544 --- [hwuam-swim-api] [-10117-exec-173] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://127.0.0.1:10118/ffice/20240305": Address already in use: connect] with root cause

java.net.BindException: Address already in use: connect
...
평군 에러율: 71797 / 87376 = 82%

평균 TPS: 866


 

 

3. 테스트 결과 분석

  • nonblock 은 TPS를 어느정도 유지하는 반면, block은 거의 죽었다시피 중간에 0에 수렴한다.
  • 트래픽 증가시 block 이 nonblock에 비해서 2배정도 에러율이 높다.
  • nonblock은 테스트시간 3분동안 지속적으로 구동된것에 비해서 block은 20초 정도에 테스트가 중단된다.(거의 통신 두절..)

 

괜히 Spring 5 부터는 webClient가 채택된것이 아님을 몸으로 느꼈다.

간단한 테스트로만 확인하더라고 성능차이가 확연하다.

여태까지는 주로 restTemplate을 사용했지만, 이젠 webClient를 고려해보자.

728x90
반응형
LIST