스프링 RestTemplate - Connection pool 설정 방법
1. RestTemplate?
- spring 3.0 부터 지원
- org.springframework.http.client
- 복잡한 HttpClient 사용을 한번 추상화한 객체
- HttpClient는 HTTP를 사용하여 통신하는 범용 라이브러리이고, RestTemplate은 HttpClient 를 추상화해서 제공
- RESTful 원칙을 지키며 단순 메소드 호출만으로 쉽게 HTTP 요청을 주고 받을 수 있도록 도와주는 HTTP 통신 템플릿
- RestTemplate 은 기본적으로 connection pool 을 사용하지 않는다.
- RestTemplate은 호출할 때마다, 로컬에서 임시 TCP 소켓을 개방하여 사용한다.
- 이렇게 사용된 TCP 소켓은 TIME_WAIT 상태가 되는데, 요청량이 많아지면 TIME_WAIT 상태의 소켓들은 재사용 될 수 없기 때문에 응답에 지연이 생김
- 응답 지연 상황을 대비하여 Connection Pool을 이용할 수 있다.
- ** Connection Pool을 설정하려면 API 서버가 Keep-Alive를 지원해야 한다.**
2. Connection pool 설정하기
- Connection Pool의 설정을 하기 위해선 객체를 생성할 때 인자로 ClientHttpRequestFactory의 구현체를 사용해야 한다.
- ClientHttpRequestFactory의 구현체인 HttpComponentsClientHttpRequestFactory를 사용할 예정이다.
- RestTemplateConfig 클래스를 만들어 Connection pool을 설정하고 Bean으로 등록시켰다.
@Configuration
public class RestTemplateConfig {
@Bean
HttpClient httpClient() {
return HttpClientBuilder.create()
.setMaxConnTotal(100) //최대 오픈되는 커넥션 수, 연결을 유지할 최대 숫자
.setMaxConnPerRoute(30) //IP, 포트 1쌍에 대해 수행할 커넥션 수, 특정 경로당 최대 숫자
.build();
}
@Bean
HttpComponentsClientHttpRequestFactory factory(HttpClient httpClient) {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(5000);
factory.setConnectTimeout(3000);
factory.setHttpClient(httpClient);
return factory;
}
@Bean
RestTemplate restTemplate(HttpComponentsClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
}
- .setMaxConnTotal(100) : Connection을 유지할 수 있는 최대 숫자 설정
- .setMaxConnPerRoute(30) : 한 개의 Route당 수행할 수 있는 Connection 최대 숫자 설정
- Connection 수에 관한 설정을 담은 HttpClient 객체를 생성
- 이 HttpClient를 이용하여 Connection 시간 설정과 함께 HttpComponetsClientHttpRequestFactory 객체를 생성
- 그 후 HttpComponetsClientHttpRequestFactory 객체를 사용하여 Restemplate에 주입을 시켜주었다.
* RestTemplate을 사용해 HTTP 요청 보내기 *
private final RestTemplate restTemplate; //DI
...
...
public void api(){
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("KEY", VALUE);
HttpHeaders headers = new HttpHeaders();
headers.add("KEY", VALUE);
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
ResponseEntity<String> response = restTemplate.exchange(
"{요청할 서버 주소}",
HttpMethod.POST, //{요청할 방식}
entity, // {요청할 때 보낼 데이터}
String.class //{요청시 반환되는 데이터 타입}
);
}
* RestTemplate 주요 메소드 *
RestTemplate Method | HTTP Method | 설명 |
execute | Any | |
exchange | Any | 헤더세팅해서 HTTP Method로 요청보내고 ResponseEntity로 반환받음 |
getForObject | GET | get 요청을 보내고 java object로 매핑받아서 반환받음 |
getForEntity | GET | get 요청을 보내고 ResponseEntity로 반환받음 |
postForLocation | POST | post 요청을 보내고 java.net.URI 로 반환받음 |
postForObject | POST | post 요청을 보내고 ResponseEntity로 반환받음 |
put | PUT | |
delete | DELETE | |
headForHeaders | HEAD | |
optionsForAllow | OPTIONS |
3. Connection pool 적용이 잘 되나 확인하기
(1) yml 파일에 로그를 출력하도록 설정을 추가
- application.yml파일에 설정 추가
logging: level: org: apache: http: DEBUG
(2) 로그를 통해 커넥션풀을 통해 Handshake가 처음에만 이루어지는지 확인
같은 API 요청을 여러 번 보냈을 때 handshake 과정을 한 번만 거치고 연결을 유지하는 것을 확인할 수 있다.
(3) API요청을 루프를 돌려 1500번 반복하고 소요된 시간을 측정해 성능 향상을 확인
Connection pool을 설정했을 때
MaxConnTotal | 연결을 유지할 최대 숫자 | 100 |
MaxConnPerRoute | 라우트당 최대 연결 숫자 | 100 |
API요청 1500번 실행 시 소요된 시간 | 91초 |
Connection pool을 적용하지 않았을 때
MaxConnTotal | 연결을 유지할 최대 숫자 | x |
MaxConnPerRoute | 라우트당 최대 연결 숫자 | x |
API요청 1500번 실행 시 소요된 시간 | 106초 |
1500번 정도만 실험했지만 시간이 줄어든 것을 확인 할 수 있었다.
(4) 성능 테스트 도구인 Apache Jmeter 사용해볼 예정
참고 출처
https://sjh836.tistory.com/141
RestTemplate (정의, 특징, URLConnection, HttpClient, 동작원리, 사용법, connection pool 적용)
참조문서 : https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html 1. RestTemplate이란? spring 3.0 부터 지원한다. 스프링에서 제공하는 http..
sjh836.tistory.com
https://minkwon4.tistory.com/216
[WEB] RestTemplate의 Connection Pool 설정
2021.01.23 - [Java&Web] - [WEB] RestTemplate을 이용하여 API 호출하기 [WEB] RestTemplate을 이용하여 API 호출하기 RestTemplate이란? RestTemplate은 Spring 3.0 부터 지원하는 템플릿으로 Spring에서 HTTP..
minkwon4.tistory.com