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));
     }
}


+ Recent posts