-
Story
-
Resolution: Unresolved
-
High
-
None
-
None
Reasons
#RestTemplate no longer under development
#WebClient supports both Sync and Async operations
Possible impacts
- Performance, need to test!
- replace Apache Client (can be configured to use if needed)
- Works with Jetty? Need to confirm
Actions
- Refresh study using a Proper proposal page
Further investigations:
- impact on error handling
- async data read/write bulk operations (possible another item)
- CpsNcmpTaskExecutor could be deprecated/removed in the future
- performance impact
A/C
- Publish and agree analysis with development team
- Performance Report (using up to 12 concurrent client) before and after. Should have no significant performance degradation
- Ensure all works with too with Apache HTTP Client 5 on the classpath
- Expose configuration parameter (if default don't suffices)
- Demo two scenarios: first the bulk interface. And the single interface (with topic)
- Ignore the failing integration tests that are failing because of the introduction of WebClient
Configure WebClient bean :
package org.onap.cps.ncmp.dmi.config; import io.netty.channel.ChannelOption; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutHandler; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.ExchangeFilterFunction; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import reactor.netty.http.client.HttpClient; import java.util.List; import java.util.concurrent.TimeUnit; @Slf4j @Configuration @AllArgsConstructor public class WebClientConfiguration { public static final int TIMEOUT = 2000; private final DmiConfiguration.SdncProperties sdncProperties; @Bean public WebClient webClient() { final var httpClient = HttpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT) // millis .doOnConnected(connection -> connection .addHandlerLast(new ReadTimeoutHandler(TIMEOUT, TimeUnit.MILLISECONDS)) // millis .addHandlerLast(new WriteTimeoutHandler(TIMEOUT, TimeUnit.MILLISECONDS))); //millis return WebClient.builder() .baseUrl(sdncProperties.getBaseUrl()) .defaultHeaders(header -> header.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)) .defaultHeaders(header -> header.setBasicAuth(sdncProperties.getAuthUsername(), sdncProperties.getAuthPassword())) .clientConnector(new ReactorClientHttpConnector(httpClient)) .filter(logRequest()) .filter(logResponse()) .build(); } private ExchangeFilterFunction logRequest() { return (clientRequest, next) -> { log.info("Request: {} {}", clientRequest.method(), clientRequest.url()); log.info("--- Http Headers: ---"); clientRequest.headers().forEach(this::logHeader); log.info("--- Http Cookies: ---"); clientRequest.cookies().forEach(this::logHeader); return next.exchange(clientRequest); }; } private ExchangeFilterFunction logResponse() { return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { log.info("Response: {}", clientResponse.statusCode()); clientResponse.headers().asHttpHeaders() .forEach((name, values) -> values.forEach(value -> log.info("{}={}", name, value))); return Mono.just(clientResponse); }); } private void logHeader(String name, List values) { values.forEach(value -> log.info("{}={}", name, value)); } }
RestTemplate should be replaced as below :
return restTemplate.exchange(sdncRestconfUrl, httpMethod, httpEntity, String.class);
WebClient GET sync call :
String response= webClient .get() .uri(resourceUrl) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .retrieve() .onStatus(HttpStatus::is4xxClientError, error -> Mono.error(new RuntimeException("API not found"))) .onStatus(HttpStatus::is5xxServerError, error -> Mono.error(new RuntimeException("Server is not responding"))) .bodyToMono(String.class) .block(); return ResponseEntity.ok(response);
WebClient POST sync call :
String response= webClient .post() .uri(resourceUrl) .body(Mono.just(jsonData), String.class) .retrieve() .onStatus(HttpStatus::is4xxClientError, error -> Mono.error(new RuntimeException("API not found"))) .onStatus(HttpStatus::is5xxServerError, error -> Mono.error(new RuntimeException("Server is not responding"))) .bodyToMono(String.class) .block(); return ResponseEntity.ok(response);
WebClient GET async call :
1. Define async call : public Mono<String> httpOperationWithJsonData(final HttpMethod httpMethod, final String resourceUrl, final String jsonData, final HttpHeaders httpHeaders) { return webClient .get() .uri(resourceUrl) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .retrieve() .onStatus(HttpStatus::is4xxClientError, error -> Mono.error(new RuntimeException("API not found"))) .onStatus(HttpStatus::is5xxServerError, error -> Mono.error(new RuntimeException("Server is not responding"))) .bodyToMono(String.class); } 2. Subscribe async call : httpOperationWithJsonDataAsync(HttpMethod.GET, getResourceUrl, null, httpHeaders) .subscribe(response -> { log.info("Get async response : {}", response); responseEntity.getBody().concat(response); });
- blocks
-
CPS-2121 CPS NCMP: http_client_requests_* metrics are not available for every endpoints or not in correct form
- Open
- relates to
-
CPS-2195 CPS NCMP: Module sync task failing with WebClient
- Closed
- split from
-
CPS-2198 CPS NCMP: Configure webClient for maximum connections into connectionpool
- Open
- split to
-
CPS-2231 Configure rate limit per host or route web client
- In Progress
-
CPS-2202 Remove un-used code of RestTemplate
- Submitted
1.
|
Refactor/adjust error handling for WebClient | Closed | Sourabh Sourabh | |
2.
|
Enhance single read/write request to use WebClient | Closed | Unassigned | |
3.
|
Enhance read bulk operation with WebClient | Open | Sourabh Sourabh | |
4.
|
Performance testing of WebClient | Open | Unassigned | |
5.
|
Replace MockRestService with MockWebServer | Closed | Sourabh Sourabh | |
6.
|
CPS NCMP: Module sync task failing with WebClient | Closed | Sourabh Sourabh | |
7.
|
Configure rate limit per host or route web client | In Progress | Sourabh Sourabh |