서버to서버 통신을 할 경우 RestClient 라이브러리를 통해 로직을 구현하곤 한다. 많이들 사용되는 것이 RestTemplate, Feign 등 인데 과거에는 그냥 기본값으로 사용했는데 MSA 환경을 고려하다보니 이것저것 추가로 고민을 하게 됐고 그 결과를 기록한다. 다만 WebClient의 경우 동작방식이 조금 다르기 때문에 여기에서 고려대상은 아니다.
1. RestClient 는 host 별로 생성해야 할까?
서버마다 타임아웃이나 default 헤더가 다를 수 있기 때문에 각각 구성하는 것이 맞다고 본다. 물론 하나의 RestClient로 하더라도 그 안에서 로직을 분기처리할 수 있지만 많은 서버와 통신해야 하는 MSA 구성의 특징을 생각하면 하나의 RestClient 에 들어가야할 분기로직이 너무 방대해질 수 있고 추후 유지보수가 힘들어 질 것 같다.
2. HttpClient 은 각 RestClient 에서 공유해서 사용해도 될까?
http 는 기본적으로 비연결형 통신이다. 기본적으로 상태가 유지되지 않고 그때그때 커넥션을 맺어서 통신한다. 그런데 HTTP/1.1 부터 Keep Alive 라는 기능을 제공하는데 이미 연결되어 있는 TCP 연결을 재사용할 수 있고 Handshake 과정이 생략되기 때문에 성능 향상을 기대할 수 있다.
RestTeamplate, Feign 는 결국 HttpClient 를 사용하는 확장 모듈인데 위에서 말하는 Keep Alive 기능 활용하기 위해서는 HttpClient의 Http Connection Pool 기능을 활용해야 한다.
그런데 1번에서 말했듯이 RestClient 는 host 별로 생성해야 하는데 각 RestClient 에서 HttpClient이나 Http Connection Pool 을 공유해도 될까? 다행히 HttpClient 는 기본적으로 thread-safe 하기 때문에 공유해서 사용해도 문제가 되진 않는다.
하지만 Http Connection Pool 는 pool 사이즈는 한정적인데 모든 RestClient 가 pool을 공유한다면 특정 host의 호출이 많아질 경우 다른 host는 상대적으로 풀을 사용하지 못하게 되는 거 아닐까?
HttpClient 모듈에서는 위와 같은 문제를 해결하기 위해 Http Connection Pool에 커넥션 생성시 host(ip+port) 당 생성할 커넥션 수를 제한하는 설정을 제공한다.
CloseableHttpClient 를 사용한다면 maxConnPerRoute를 통해 이를 설정할 수 있고 OkHttpClient 를 사용한다면 maxRequestsPerHost 통해 이를 설정할 수 있다. 참고로 OkHttpClient 에서는 굳이 설정하지 않더라도 default 값이 5로 할당된다.
'Backend > Spring+Boot' 카테고리의 다른 글
의존성 주입시 중복되는 타입에 대한 처리 (0) | 2021.07.23 |
---|---|
Spring에서 권장되는 의존성 주입 방법 (0) | 2021.07.23 |
UriComponentsBuilder (0) | 2021.07.19 |
@RunWith(SpringRunner.class) (0) | 2021.07.13 |
@Async 설정 (0) | 2021.07.13 |