package com.sample;
import java.util.concurrent.TimeUnit;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import lombok.extern.slf4j.Slf4j;
/**
* Spring RestTemplate 샘플
* - 타임아웃 및 pool설정 등의 튜닝버전
*
* @author
*/
@Slf4j
public class RestTemplateSample {
private static final String REQ_URL_1 = "https://테스트URL 1번째";
private static final String REQ_URL_2 = "https://테스트URL 2번째";
private static RestTemplate restTemplate = new RestTemplate();
public static void init() {
log.info("== Start : restTemplate 초기화");
HttpComponentsClientHttpRequestFactory crf = new HttpComponentsClientHttpRequestFactory();
crf.setReadTimeout(7000); //읽기시간초과 타임아웃
crf.setConnectTimeout(7000); //연결시간초과 타임아웃
// @formatter:off
HttpClient httpClient = HttpClientBuilder.create()
.setMaxConnTotal(300) //커넥션풀적용(최대 오픈되는 커넥션 수)
.setMaxConnPerRoute(50) //커넥션풀적용(IP:포트 1쌍에 대해 수행 할 연결 수제한)
.evictIdleConnections(2000L, TimeUnit.MILLISECONDS) //서버에서 keepalive시간동안 미 사용한 커넥션을 죽이는 등의 케이스 방어로 idle커넥션을 주기적으로 지움
.build();
crf.setHttpClient(httpClient);
// @formatter:on
restTemplate.setRequestFactory(crf);
log.info("== end : restTemplate 초기화\n\n");
}
/**
* Spring RestTemplate 샘플
* - 타임아웃 및 pool설정 등의 튜닝버전
* - https URL호출 테스트시, 로그에 SSLConnectionSocketFactory 존재 유무 등을 확인하면 pool이 활용되어 https three hand shake가 발생하는지 알 수 있음
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
init();
int testReqCnt = 3; //테스트 호출 횟수
//1번째 요청시 커넥션을 맺어서 pool에 넣고, 2번째 요청부터는 pool을 재사용(로그를 보면 ssl핸드쉐이크 부분이 2번째에서는 없음)
for (int i = 1; i <= testReqCnt; i++) {
System.out.println("\n\n" + i + "번째 요청 시작");
log.info("\n\nURL:{}의 {} 번째 결과. {}\n\n\n", REQ_URL_1, i, restTemplate.getForObject(REQ_URL_1, String.class));
//evictIdleConnections 확인시 주석 풀어서 실행=> 로그에 "Closing connections idle longer than 2000 MILLISECONDS" 확인 됨
Thread.sleep(3000);
if (i != testReqCnt) {
log.info("\n\n3초 sleep 후 idleConnection이 pool에서 제거된 후 해당URl을 재 요청해봄\n\n");
}
}
System.out.println("\n\n\n\n");
System.out.println("=== 2번째 URL호출 테스트 시작 ===");
for (int i = 1; i <= testReqCnt; i++) {
System.out.println("\n\n" + i + "번째 요청 시작");
log.info("\n\nURL:{}의 {} 번째 결과. {}\n\n\n", REQ_URL_2, i, restTemplate.getForObject(REQ_URL_2, String.class));
}
System.out.println("\n\n\n\n");
System.out.println("1번째 URL 재 호출해봄");
log.info("\n\nURL:{}의결과. {}\n", REQ_URL_1, restTemplate.getForObject(REQ_URL_1, String.class));
}
}