티스토리 뷰
이번 들에서는 기존에 WebFlux 와 MVC 패턴을 이용한 NonBlocking, Blocking 테스트를 진행 하며 성능을 측정해 보도록 하겠습니다.
1. 테스트 tool 로는 K6 사용
공식홈페이지 : https://k6.io/
* k6 결과 값
- vus — 활성 가상 사용자 수
- vus_max — 테스트에 할당 된 최대 가상 사용자
- iterations— default함수가 호출 된 총 횟수
- iteration_duration— default함수 를 실행하는 데 걸린 총 시간
- dropped_iterations— iterations시작할 수없는 수
- data_received — 수신 된 데이터의 양
- data_sent — 전송 된 데이터 양
- checks — 성공적인 검사 비율
- http_reqs — k6에 의해 생성 된 총 요청
- http_req_blocked — 요청을 시작하기 전에 사용 가능한 TCP 연결을 기다리는 데 소요 된 시간
- http_req_connecting — TCP 연결 설정에 소요 된 시간
- http_req_tls_handshaking — TLS 핸드 쉐이킹에 소요 된 시간
- http_req_sending — 데이터 전송에 소요 된 시간
- http_req_waiting — 원격 호스트의 응답을 기다리는 데 소요 된 시간
- http_req_receiving — 데이터 수신에 소요 된 시간
- http_req_duration— 요청에 대한 총 시간. http_req_sending+ http_req_waiting+를 기준으로 계산됩니다.http_req_receiving.
2. WebFlux VS MVC 단순 호출 테스트
=> 테스트 하려면 dependency 변경해 줘야함
implementation 'org.springframework.boot:spring-boot-starter-web'
<=>
implementation 'org.springframework.boot:spring-boot-starter-webflux'
WebFlux
public Mono <ServerResponse> webfluxTest(ServerRequest req) {
return ok().body(Flux.just("WebFlux Test", "OK!"), String.class);
}
MVC
@GetMapping("/nonWebFluxTest")
public String nonWebFluxTest() {
return "Non WebFlux Test OK!";
}
Test.js
// test.js
import http from 'k6/http';
import { sleep } from 'k6';
export default function() {
//http.get('http://localhost:8080/nonWebFluxTest'); // get MVC test
http.get('http://localhost:8080/webFluxTest'); // get WebFlux test
}
2. WebFlux VS MVC 외부 호출 테스트
vus : 가상이용자수
duration : 테스트 시간
out : 결과 출력 포맷 (json, text, csv ...)
k6 run --vus 10 --duration 30s --out json=out.json test
WebFlux 테스트 결과
MVC 테스트
두개의 API 서버를 구성하여 WebClient 로 호출 시에 성능 테스트
API 호출 부
MVC version (RestTamplate)
@Controller
public class HelloController {
@Autowired
private TestService testService;
@ResponseBody
@GetMapping("/nonWebFluxTest")
public String nonWebFluxTest() {
testService.callTestService();
return "Non WebFlux Test OK!";
}
}
@Service
public class TestService {
@Autowired
private ApiService apiService;
public String callTestService() {
try {
String res = apiService.callAPI("http://localhost:9090/", HttpMethod.GET);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return "OK";
}
}
@Service
public class ApiService {
public String callAPI(String url, HttpMethod httpMethod) throws JsonProcessingException {
HashMap<String, Object> result = new HashMap<String, Object>();
String jsonInString = "";
try {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(5000); //타임아웃 설정 5초
factory.setReadTimeout(5000);//타임아웃 설정 5초
RestTemplate restTemplate = new RestTemplate(factory);
HttpHeaders header = new HttpHeaders();
HttpEntity<?> entity = new HttpEntity<>(header);
UriComponents uri = UriComponentsBuilder.fromHttpUrl(url).build();
//이 한줄의 코드로 API를 호출해 MAP타입으로 전달 받는다.
ResponseEntity<Map> resultMap = restTemplate.exchange(uri.toString(), httpMethod, entity, Map.class);
result.put("statusCode", resultMap.getStatusCodeValue()); //http status code를 확인
result.put("header", resultMap.getHeaders()); //헤더 정보 확인
result.put("body", resultMap.getBody()); //실제 데이터 정보 확인
//데이터를 제대로 전달 받았는지 확인 string형태로 파싱해줌
ObjectMapper mapper = new ObjectMapper();
jsonInString = mapper.writeValueAsString(resultMap.getBody());
} catch (HttpClientErrorException | HttpServerErrorException e) {
result.put("statusCode", e.getRawStatusCode());
result.put("body" , e.getStatusText());
System.out.println(e.toString());
} catch (Exception e) {
result.put("statusCode", "999");
result.put("body" , "excpetion오류");
System.out.println(e.toString());
}
return jsonInString;
}
}
@Controller
public class TestWebController {
@ResponseBody
@GetMapping
public String pong() {
return "pong";
}
}
WebFlux version
@Service
public class WebFluxApiService {
@Autowired
private WebClient webClient;
public Mono<String> get(String url) {
return webClient
.get()
.uri(url)
.retrieve()
.bodyToMono(String.class)
;
}
}
public Mono <ServerResponse> webfluxTest(ServerRequest req) {
Mono<String> res = apiService.get("http://localhost:9090/");
return ok().body(Flux.just("WebFlux Test", "OK!"), String.class);
}
호출 API 코드
@Controller
public class TestWebController {
@ResponseBody
@GetMapping
public String pong() {
return "pong";
}
}
* 테스트 결과
MVC
WebFlux
iteratoin_duration 비교
mvc : avg 3.07ms
webFlux : avg 1.55ms
3. MVC => WebFlux 로 변경
https://pkgonan.github.io/2019/06/webflux-asynchronous-non-blocking-io-tuning
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- data crawling
- 웹개발
- EC2
- MSA
- SpringBoot
- Python
- Python #FastAPI
- 퀜트백
- kafka
- TDD
- GateWayApi
- nodejs
- data mining
- 분산처리
- AWS
- fastapi
- 켄트 백
- 테스트주도개발
- MQ
- 테스트 주도 개발
- 테스트
- mongodb
- 웹서비스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함