RestTemplate (or WebClient) per destination socket and connect timeouts - spring

Is there a way with either client (RestTemplate or the newer WebClient) to set per destination socket or connect timeouts? For example in an API aggregation web service, where I talk to several different services/hosts, it's often desirable to have different socket timeouts based on if the services are internal or external/3rd party. The only solution I know of (with RestTemplate, I haven't used WebClient) is to instantiate a separate RestTemplate with a different socket timeout/connect timeout (and do this for each host that requires a different timeout).
This is fairly annoying because the amount of setup code required for a RestTemplate configured with HttpComponents is non-trivial, and having to add #Qualifier at every use of RestTemplate injection is also non-ideal. Further, the fact that HttpComponents allows for max total connections and max routes to host implies that one RestTemplate talking to all outbound traffic is the expected usage.

Related

set InputBufferSize and Timeout of connection for Netty (Reactive Spring) and heartbeats in Reactive WebSocket?

Maybe somebody has experienced this and can help me out.
I have a Reactive WebSocket server (WebFlux Spring Boot).
I checked the connection to the server by Postman and all is good, the connection lasts a long time, but I don't know how long this connection will last with another clients, so I want to set a couple of parameters: InputBufferSize and Timeout, I found how can do it for some servers (Jetty, TomCat,..):
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#websocket-server-runtime-configuration
But I cannot find how can do it for Netty (I use Reactive WebSocket, based on Netty).
How can set InputBufferSize and Timeout of connection for Netty (Reactive Spring)?
And another question is how to send ping-pong (heartbeats), I think I can do it in MyHandler (that implements org.springframework.web.reactive.socket.WebSocketHandler), in
#Override
public Mono handle(WebSocketSession session)
WebSocketMessage has field type (enum: TEXT, BINARY, PING, PONG) I can use it for ping-pong (heartbeats) between any client and my server part. But many forums write that the Netty has already implemented this process (ping-pong) and it will be superfluous - to add it manually in WebSocketHandler. I'm confused here, should I write additional processing (ping-pong in WebSocketHandler) or it will be an unnecessary layer on top of the already made part in Netty?

Connection pooling in spring WebClient

I want to use Spring WebClient in a project to consume some external web service.
Can WebClient object be singleton or shared among all threads (requests)?
If my application is going to get millions of requests per second, then do I need to pool WebClient Objects? If yes, I am unable to find any documentation or examples.
Does mono.block() internally work similar to future.get() or latch.await()?
The WebClient is a non-blocking implementation of a REST client built on the Reactive Stack, so I guess the only issue you should focus on is to complete a non-blocking call.
Can WebClient object be a singleton or shared among all threads (requests)?
A standard way I have seen everywhere is to inject WebClient as a bean. I find no reason to do any different.
#Autowired
WebClient webClient;
If my application is going to get millions of requests per second, then do I need to pool WebClient Objects?
That's a lot! This should definitely need to be solved with service replication, load-balancers, bulkhead, etc. In terms of the client itself, see the following performance of reactive client using newer versions of Spring: WebFlux Reactive Programming Performance Test. Moreover, that is the expected maximal throughput?
Does mono.block() internally work similar to future.get() or latch.await()?
Yes, it does.

How to make a socket server that listens for client connections and opens a socket once an Endpoint is called in Spring?

I have an application that opens a "HttpURLConnection" to a printer. The printer is listening for socket connection and makes a connection when a new TCP socket connection is opened on the Application side (In this case through a new "HttpURLConnection"). Now, I want to mock this printer.
In the Application an Http call is made to the printer server and a socket connection is established between the Application and the server. How do I mock this printer as a spring boot application.
Sounds like you need to take a look into Spring Test Framework and especially its part about a Web: https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/testing.html#spring-mvc-test-client
I would really investigate a possibility to interact via a RestTemplate instead of direct HttpURLConnection and then use that MockRestServiceServer for mocking requests and responses.
Another way is to use a #SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) and implement controller with appropriate mappings and possible return results. This way you would be able to use the mentioned HttpURLConnection to connect to randomly allocated port for HTTP server and perform requests as in production.

Jax rs client pool

I am working on setting up a REST Client using jax-rs 2 client API.
In the api doc it says "Clients are heavy-weight objects that manage the client-side communication infrastructure. Initialization as well as disposal of a Client instance may be a rather expensive operation. It is therefore advised to construct only a small number of Client instances in the application." (https://docs.oracle.com/javaee/7/api/javax/ws/rs/client/Client.html). As per this statement it sounds like Client is not thread-safe and i should not be using single Client instance for all requests.
I am using CXF implementation, so far i didn't find a way to set up pool for Client objects.
If anyone has any information reg this could you please share.
Thanks in advance.
By default, CXF uses a transport based on the in-JDK HttpURLConnection object to perform HTTP requests.
Connection pooling is performed allowing persistent connections to reuse the underlying socket connection for multiple http requests.
Set these system properties to configure the pool(default values)
http.keepalive=true
http.maxConnections=5
Increment the value of http.maxConnections to set the maximum number of idle connections that will be simultaneously kept alive, per destination. See in this link the complete list of properties properties.html
In this post are explained some detail how it works
Java HttpURLConnection and pooling
Note also that the default JAX-RS client is not thread-safe by default. Check the limitations for proper use here
When you need many requests executed simultaneosly CXF can also use the asynchronous apache HttpAsyncClient. Ser details here
http://cxf.apache.org/docs/asynchronous-client-http-transport.html

Reuse jax-ws client proxies for different addresses

I have a bunch of web services servers (around 200) running on the same machine which expose the same service on different ports.
I have a client which perform tasks which include calling the service on different servers.
Something like:
while (true) {
task = readTask();
runHelloService(task.serverAddress)
}
I was wondering what is the best way to generate the HelloService client proxy.
Can I generate one and replace the target address before each call?
Should i generate a client per server (which means 200 client proxies) and use the relevant one?
I will probably want to run the above loop concurrently on several threads.
Currently I have only one proxy which is generated by spring and cxf with the jaxws:client declaration.
This is an interesting use case. I believe that changing the endpoint whilst sharing the proxy amongst multiple threads will not work. There is a one-to-one relationship between a client proxy and a conduit definition. Changes to a conduit are explicitly not thread safe.
I recommend eschewing Spring configuration altogether to create client proxies and instead use programmatic construction of the 200 client proxies.
See also Custom CXF Transport - Simplified Client Workflow.

Resources