[SPRING] 전통적인 서블릿 다중 스레드 응용 프로그램에서 봄 부팅 WebClient.Builder 콩 사용
SPRING전통적인 서블릿 다중 스레드 응용 프로그램에서 봄 부팅 WebClient.Builder 콩 사용
나는 스프링 클라이언트에서 다른 마이크로 서비스를 호출 할 수있는 HTTP 클라이언트를 가지고 싶습니다. RestTemplate이 사용되지 않으므로 WebClient.Builder 및 WebClient를 사용하려고했습니다. 스레드의 안전성에 대해서는 확신하지 못합니다. 여기 예 :
@Service
public class MyService{
@Autowired
WebClient.Builder webClientBuilder;
public VenueDTO serviceMethod(){
//!!! This is not thread safe !!!
WebClient webClient = webClientBuilder.baseUrl("http://localhost:8000").build();
VenueDTO venueDTO = webClient.get().uri("/api/venue/{id}", bodDTO.getBusinessOutletId()).
retrieve().bodyToMono(VenueDTO.class).
blockOptional(Duration.ofMillis(1000)).
orElseThrow(() -> new BadRequestException(venueNotFound));
return VenueDTO;
}
}
이 예제의 serviceMethod ()는 몇 개의 스레드에서 호출되며 webClientBuilder는 단일 Bean 인스턴스입니다. WebClient.Builder 클래스에는 state : baseUrl이 포함되어 있으며이 상태 업데이트를 동시에 호출 할 수있는 스레드가 거의 없으므로 스레드로부터 안전하지 않은 것으로 보입니다. 그 사이에 WebClient 자체가 스레드 안전합니다 답변을 스프링에서 WebClient를 멀티 스레드 환경에서 사용하는 올바른 방법
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-webclient.html에서 언급 한 WebClient.Builder 빈을 사용해야합니까?
내가 보게되는 해결 방법 중 하나는 빌더에 전달 된 상태를 사용하지 않고 WebClient를 작성하는 것입니다.
WebClient webClient = webClientBuilder.baseUrl("http://localhost:8000").build();
내가 할 것이다:
WebClient webClient = webClientBuilder.build();
uri 메소드 호출에서 프로토콜과 포트로 전체 url을 전달하십시오.
webClient.get().uri("full url here", MyDTO.class)
내 경우에 그것을 사용하는 적절한 방법은 무엇입니까?
해결법
-
==============================
1.맞습니다. WebClient.Builder는 스레드로부터 안전하지 않습니다.
맞습니다. WebClient.Builder는 스레드로부터 안전하지 않습니다.
스프링 부트는 WebClient.Builder를 프로토 타입 빈으로 생성하므로 각 주입 지점에 대해 새로운 인스턴스를 얻습니다. 귀하의 경우 귀하의 구성 요소가 제 생각에 약간 이상하게 보입니다.
오히려 다음과 같이 보일 것입니다.
@Service public class MyService{ private final WebClient webClient; public MyService(WebClient.Builder webClientBuilder) { this.webClient = webClientBuilder.baseUrl("http://localhost:8000").build(); } public VenueDTO serviceMethod(){ VenueDTO venueDTO = webClient.get().uri("/api/venue/{id}", bodDTO.getBusinessOutletId()). retrieve().bodyToMono(VenueDTO.class). blockOptional(Duration.ofMillis(1000)). orElseThrow(() -> new BadRequestException(venueNotFound)); return VenueDTO; } }
이제 이것이 코드 스 니펫이고 응용 프로그램에 다른 제약이있을 수 있습니다.
애플리케이션이 기본 URL을 자주 변경해야하는 경우 빌더에서 구성을 중지하고 질문에 언급 된 전체 URL을 전달해야한다고 생각합니다. 응용 프로그램에 다른 요구 사항 (인증 등에 대한 사용자 정의 헤더 등)이있는 경우 빌더에서 또는 요청별로이를 수행 할 수 있습니다.
일반적으로 구성 요소마다 단일 WebClient 인스턴스를 만들어야합니다. 각 요청에 대해 다시 작성하는 것은 매우 낭비입니다.
응용 프로그램에 매우 특정한 제약 조건이있어 실제로 다른 인스턴스를 만들어야하는 경우에는 항상 webClientBuilder.clone ()을 호출하고 스레드 안전성 문제없이 변경할 수있는 빌더의 새 인스턴스를 가져올 수 있습니다.
from https://stackoverflow.com/questions/54136085/spring-boot-webclient-builder-bean-usage-in-traditional-servlet-multi-threaded-a by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] DTO 및 Entity 클래스 이름 지정 (0) | 2019.05.27 |
---|---|
[SPRING] 런타임 생성자 인자를 가진 메소드에서 스프링 빈을 인스턴스화하는 방법? (0) | 2019.05.27 |
[SPRING] java / spring- NoClassDefFoundError를 org.springframework.context.support.AbstractApplicationContext에서 얻는다. (0) | 2019.05.27 |
[SPRING] 스프링 체크 박스 태그를 struts2 체크 박스로 변환하는 방법은 무엇입니까? (0) | 2019.05.26 |
[SPRING] classpath에서 spring.xml의 인쇄 경로 (0) | 2019.05.26 |