다중 스레드 환경에서 Spring Web Client를 사용하는 올바른 방법
Spring Framework 관련해서 한가지 질문이 있습니다. WebClient
애플리케이션에서 유사한 API 호출을 많이 해야 하고, 때로는 호출(Authentication Token)에서 헤더를 변경해야 합니다.따라서 다음 두 가지 옵션 중 무엇이 더 나을지에 대한 의문이 생깁니다.
- MyService.class로 수신되는 모든 요청에 대해 하나의 WebClient를 만들려면 다음과 같이 하십시오.
private final
필드, 아래 코드와 같습니다.
private final WebClient webClient = WebClient.builder()
.baseUrl("https://another_host.com/api/get_inf")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.build();
여기에 또 다른 질문이 있습니다.WebClient
안전하다고요?(많은 스레드에서 서비스를 사용하기 때문에)
- 서비스 클래스로 들어오는 각 새 요청에 대해 새 WebClient를 만듭니다.
최대한의 성능을 제공하고 올바른 방법으로 사용하고 싶은데 방법을 모르겠습니다.WebClient
그 안에서 작동하고 어떻게 사용될 것인지에 대해 생각합니다.
감사해요.
여기서 두가지 중요한 것은WebClient
:
- HTTP 리소스(연결, 캐시 등)는 기본 라이브러리에 의해 관리되며 참조됩니다.
ClientHttpConnector
에 구성할 수 있습니다.WebClient
WebClient
불변의
이 점을 염두에 두고 동일한 것을 다시 사용하도록 노력해야 합니다.ClientHttpConnector
애플리케이션 전체에 걸쳐 연결 풀을 공유할 수 있기 때문에 이는 성능에 있어 가장 중요한 것임에 틀림없습니다.이것은 당신이 모든 것을 유도해야 한다는 것을 의미합니다.WebClient
같은 예에서 나온 예들WebClient.create()
불러.Spring Boot
를 생성하고 구성함으로써 이를 지원합니다.WebClient.Builder
당신의 앱 어디에서나 주사할 수 있는 콩.
왜냐면WebClient
실을 안전하게 쓸 수 있습니다.WebClient
특정 스레드에 연결된 것이 없는 반응형 환경에서 사용하도록 되어 있습니다(기존의 서블릿 애플리케이션에서는 사용할 수 없음을 의미하지는 않습니다).
요청하는 방법을 변경하려면 다음과 같은 몇 가지 방법이 있습니다.
빌드 단계에서 구성
WebClient baseClient = WebClient.create()
.baseUrl("https://example.org");
요청 단위로 구성합니다.
Mono<ClientResponse> response = baseClient.get()
.uri("/resource")
.header("token", "secret")
.exchange();
기존 인스턴스에서 새 클라이언트 인스턴스 만들기
// mutate() will *copy* the builder state and create a new one out of it
WebClient authClient = baseClient.mutate()
.defaultHeaders(hdrs -> {hdrs.add("token", "secret");})
.build();
제 경험으로는 제어할 수 없는 서버에서 외부 API를 호출하는 경우 WebClient를 아예 사용하지 않거나 풀링 메커니즘을 끈 상태에서 사용합니다.연결 풀링으로 인한 성능 향상은 원격 호스트 등에 의해 다른 API 호출이 갑자기 종료되었을 때 한 API 호출에서 랜덤 오류를 발생시키는 (기본 reactor-netty) 라이브러리에 내장된 가정에 의해 크게 과대평가됩니다.모든 호출이 공유 작업자 스레드에서 이루어지므로 오류가 발생한 위치를 알 수 없는 경우도 있습니다.
휴지 템플릿에 대한 문서에서 앞으로 감가상각이 될 것이라고 해서 웹클라이언트를 사용하는 실수를 했습니다.나중에 생각해보면, 일반 HttpClient 또는 Apache Commons HttpClient를 사용하고 싶지만, 만약 당신이 나와 같고 WebClient로 이미 구현되어 있다면, 당신은 다음과 같이 WebClient를 만들어 풀링을 끌 수 있습니다.
private WebClient createWebClient(int timeout) {
TcpClient tcpClient = TcpClient.newConnection();
HttpClient httpClient = HttpClient.from(tcpClient)
.tcpConfiguration(client -> client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeout * 1000)
.doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(timeout))));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
*** 별도의 WebClient를 작성한다고 해서 WebClient에 별도의 연결 풀이 있는 것은 아닙니다.HttpClient.create 코드만 보면 HttpResources.get()을 호출하여 전역 리소스를 가져옵니다.수동으로 풀 설정을 제공할 수는 있지만 기본 설정에서도 발생하는 오류를 고려하면 위험을 감수할 가치가 없다고 생각합니다.
언급URL : https://stackoverflow.com/questions/49095366/right-way-to-use-spring-webclient-in-multi-thread-environment
'code' 카테고리의 다른 글
창을 사용하여 파일을 다운로드하려면 어떻게 해야 합니까?가져오라고요? (0) | 2023.09.20 |
---|---|
오라클 datetime 필드 색인 (0) | 2023.09.20 |
여러 열에 FULLTEXT 인덱스를 만드는 방법은? (0) | 2023.09.20 |
활성 레코드:: 접속TimeoutError: 5.000초(대기 5.000초) 내에 데이터베이스 연결을 가져올 수 없습니다. (0) | 2023.09.20 |
Oracle INSERT를 하나의 쿼리로 두 개의 테이블에 입력 (0) | 2023.09.20 |