ExecutorService or new Threads in asynchronous jax-rs - jax-rs

I've been looking over Asynchronous services in jersey, I see that we delegate the processing to a new thread and let it handle returning the response. I have two approaches to thread execution
Creating anonymous threads and starting them in the resource method itself
Using ExecutorService to make a fixedThreadPool and delegating thread execution to executor
I'm concerned that using 1 would mean writing more boilerplate code and using 2 would essentially mean that the amount of throughput I generate from the system is limited by the size of executor thread pool. I'm sure that such a situation is common and I'm looking for some tested patterns or implementations which would help me in this.

If you go with option 2, you can use dependency injection using #Inject annotation and HK2 AbstractBinder to instantiate a Resource constructor or a member variable. This allows you to change the executor service used by the Resource (i.e., the type of executor service used by the Resource is configurable).

Related

ThreadLocal in spring web flux

I am new to spring webflux. I am trying to implement the ThreadLocal using spring webflux.
I have a requirement where I need to pass the header from one microservice to another microservice in webclient.
I do not want to pass the header from on service to another service carrying it manually and assigning it in each request.
So thought of using ThreadLocal when I can set it and can access that in webclient call.
I am try to find a sample application where I can refer ThreadLocal with in spring webflux.
You should not use ThreadLocal in reactive environment. Webflux (which based on Reactor) is a non blocking framework. It reuses threads so the steps of one reactive pipeline can run in different threads and also multiple requests can use the same thread concurrently - until one waits, another operation will be picked and executed. Imagine if your request puts something into threadlocal and waits - for example - on a db select, another request can override this value and the next pipeline stage of the original request will see that new value belongs to another request. Threadlocal is good for request-per-thread model.
For webflux, you can use contexts. For example put the value into the pipeline in a WebFilter, then you can retrieve it in any point of the reactive pipeline:
chain.filter(exchange).contextWrite(<your data>)
In the pipeline (in map/flatmap...)
Mono.deferContextual(...)
Here is the link for documentation.
Alternatively you can lift ThreadLocal's value on every operation using Hooks, but this is not a nice and bulletproof solution.

Spring bean RequestScope with Webflux

Is there a pattern to use #RequestScope with Webflux? We used the approach suggested here (https://www.baeldung.com/spring-bean-scopes) but it gives below error.
No scope registered for scope name request
Request scope works on ThreadLocal which is not supported by Webflux because part of work can be delegated between threads and you cannot assume that request will be handled by one thread.
In such a case, you should take a look at Reactor Context which allows you to connect data with the request scope.

WebFlux Controllers Returning Flux and Backpressure

In Spring WebFlux I have a controller similar to this:
#RestController
#RequestMapping("/data")
public class DataController {
#GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public Flux<Data> getData() {
return <data from database using reactive driver>
}
}
What exactly is subscribing to the publisher?
What (if anything) is providing backpressure?
For context I'm trying to evaluate if there are advantages to using Spring WebFlux in this specific situation over Spring MVC.
Note: I am not a developer of spring framework, so any comments are welcome.
What exactly is subscribing to the publisher?
It is a long living subscription to the port (the server initialisation itself). Therefore, the ReactorHttpServer.class has the method:
#Override
protected void startInternal() {
DisposableServer server = this.reactorServer.handle(this.reactorHandler).bind().block();
setPort(((InetSocketAddress) server.address()).getPort());
this.serverRef.set(server);
}
The Subscriber is the bind method, which (as far as I can see) does request(Long.MAX_VALUE), so no back pressure management here.
The important part for request handling is the method handle(this.reactorHandler). The reactorHandler is an instance of ReactorHttpHandlerAdapter. Further up the stack (within the apply method of ReactorHttpHandlerAdapter) is the DispatcherHandler.class. The java doc of this class starts with " Central dispatcher for HTTP request handlers/controllers. Dispatches to registered handlers for processing a request, providing convenient mapping facilities.". It has the central method:
#Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
return Flux.fromIterable(this.handlerMappings)
.concatMap(mapping -> mapping.getHandler(exchange))
.next()
.switchIfEmpty(createNotFoundError())
.flatMap(handler -> invokeHandler(exchange, handler))
.flatMap(result -> handleResult(exchange, result));
}
Here, the actual request processing happens. The response is written within handleResult. It now depends on the actual server implementation, how the result is written.
For the default server, i.e. Reactor Netty it will be a ReactorServerHttpResponse.class. Here you can see the method writeWithInternal. This one takes the publisher result of the handler method and writes it to the underlying HTTP connection:
#Override
protected Mono<Void> writeWithInternal(Publisher<? extends DataBuffer> publisher) {
return this.response.send(toByteBufs(publisher)).then();
}
One implementation of NettyOutbound.send( ... ) is reactor.netty.channel.ChannelOperations. For your specific case of a Flux return, this implementation manages the NIO within MonoSendMany.class. This class does subscribe( ... ) with a SendManyInner.class, which does back pressure management by implementing Subscriber which onSubscribe does request(128). I guess Netty internally uses TCP ACK to signal successful transmission.
So,
What (if anything) is providing backpressure?
... yes, backpressure is provided, e.g. by SendManyInner.class, however also other implementations exist.
For context I'm trying to evaluate if there are advantages to using Spring WebFlux in this specific situation over Spring MVC.
I think, it is definitely worth evaluating. For performance I however guess, the result will depend on the amount of concurrent requests and maybe also on the type of your Data class. Generally speaking, Webflux is usually the preferred choice for high throughput, low latency situations, and we generally see better hardware utilization in our environments. Assuming you take your data from a database you probably will have the best results with a database driver that too supports reactive. Besides performance, the back pressure management is always a good reason to have a look at Webflux. Since we adopted to Webflux, our data platform never had problems with stability anymore (not to claim, there are no other ways to have a stable system, but here many issues are solved out of the box).
As a side note: I recommend, having a closer look at Schedulers we just recently gained 30% cpu time by choosing the right one for slow DB accesses.
EDIT:
In https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-fn-handler-functions the reference documentation explicitly says:
ServerRequest and ServerResponse are immutable interfaces that offer JDK 8-friendly access to the HTTP request and response. Both request and response provide Reactive Streams back pressure against the body streams.
What exactly is subscribing to the publisher?
The framework (so Spring, in this case.)
In general, you shouldn't subscribe in your own application - the framework should be subscribing to your publisher when necessary. In the context of spring, that's whenever a relevant request hits that controller.
What (if anything) is providing backpressure?
In this case, it's only restricted by the speed of the connection (I believe Webflux will look at the underlying TCP layer) and then request data as required. Whether your upstream flux listens to that backpressure though is another story - it may do, or it may just flood the consumer with as much data as it can.
For context I'm trying to evaluate if there are advantages to using Spring WebFlux in this specific situation over Spring MVC.
The main advantage is being able to hold huge numbers of connections open with only a few threads - so no overhead of context switching. (That's not the sole advantage, but most of the advantages generally boil down to that point.) Usually, this is only an advantage worth considering if you need to hold in the region of thousands of connections open at once.
The main disadvantage is the fact reactive code looks very different from standard Java code, and is usually necessarily more complex as a result. Debugging is also harder - vanilla stack traces become all but useless for instance (though their are tools & techniques to make this easier.)

ElasticClient Dispose

I'm new to this. I'm working with ElasticClient (.Net) and I was curious if:
Is it thread safe? I assume so because it uses pooling.
Should I do anything to clean up the client resources when I'm done? It does not implement IDisposable.
Thanks!
Bob
On thread safety: https://github.com/elastic/elasticsearch-net/issues/23
The ElasticClient holds a single IConnection responsible for doing
async and sync http calls. The IConnection does not reuse
httprequests and uses thread local state for data thats being passed
around during the stages of the request. It should thus be thread
safe.
On disposing: https://github.com/elastic/elasticsearch-net/issues/101
ElasticClient is almost stateless except for a static CLR type info
cache that is threadsafe so you can even use one client over threads.
Disposing is also handled by Nest and ElasticClient only exposes
POCO's.

EJB3 Singleton Session Bean and ConcurrentHashMap

If using a EJB3 Singleton Session Bean, there is no point to having ConcurrentHashMap state variable - correct? I can just use a regular HashMap that will be managed by the Container Concurrency Manager ?
That is correct. If nothing else is specified, by default singleton session bean uses container managed concurrency. Further, if not specified, every business and timeout method have by default LockType.WRITE. Result is that there is not multiple threads concurrently executing methods in singleton and as consequence using regular java.util.HashMap is perfectly fine.
The default is #ConcurrencyManagement(CONTAINER) with #Lock(WRITE) for all methods, which won't scale as nicely as a ConcurrentHashMap since all method calls will block waiting for the write lock. You could use #Lock(READ) and ConcurrentHashMap to allow multiple threads, but at that point, you might as well use #ConcurrencyManagement(BEAN) to get rid of the container-managed concurrency altogether.