Правильный способ использования Spring WebClient в многопоточной среде

у меня есть один вопрос относительно Весна WebClient

в моем приложении мне нужно сделать много подобных вызовов API, иногда мне нужно изменить заголовки в вызовах (токен аутентификации). Поэтому возникает вопрос, что было бы лучше из двух вариантов:

  1. чтобы создать один WebClient для всех входящих запросов к MyService.класс, сделав это 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 потокобезопасным? (потому что сервис используется многими нитями)

  1. для создания нового WebClient для каждого нового запроса, входящего в класс обслуживания.

Я хочу обеспечить максимальную производительность и использовать его правильно, но я не знаю, как WebClient работает внутри него, и как он ожидает быть использован.

спасибо вы.

1 ответов


две ключевые вещи о WebClient:

  1. его HTTP-ресурсы (соединения, кэши и т. д.) управляются базовой библиотекой, на которую ссылается ClientHttpConnector что вы можете настроить на WebClient
  2. WebClient - это непреложный

имея это в виду, вы должны попытаться повторно использовать то же самое ClientHttpConnector в вашем приложении, потому что это будет общий пул соединений - это, возможно, самое важное для производительности. Это средство вы должны попытаться вывести all WebClient экземпляры из того же WebClient.create() звонок. Spring Boot поможет вам в этом, создав и настроив для вас WebClient.Builder bean, который вы можете ввести в любом месте вашего приложения.

, потому что WebClient неизменяемо это потокобезопасно. WebClient предназначен для использования в реактивной среде, где ничего не привязано к определенному потоку (это не означает, что вы не можете использовать в традиционном приложении сервлета).

если вы хотите изменить способ запросы сделаны, есть несколько способов добиться этого:

настройка вещей на этапе builder

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(headers -> {headers.add("token", "secret");})
                .build();