Mono<List<T>> difference with Flux<T> in Spring webflux - spring-webflux

My understand is Mono<List<T>> is a synchronized Flux<T>
and Flux could not be a rest api response.
Am I right?
If not, what's the different between Mono<List<T>> and Flux<T>
or could a Flux could be a rest api response in some where ?

as a return type, Mono<List<T>> means that you'll get asynchronously a full list of T elements in one shot.
Flux<T> means that you'll get zero to many T elements, possibly one by one as they come.
If you're getting such return types from an HTTP client such as WebClient, Mono<List<T>> and Flux<T> might be more or less equivalent from a runtime perspective, if the returned Content-Type is for example "application/json". In this case, the decoder will deserialize the response in one shot. The only different is, Flux<T> provides more interesting operators and you can always collectList and fall back to a Mono<List>.
On the other hand, if the returned Content-Type is a streaming one, for example "application/stream+json" then this definitely has an impact as you'll get the elements one by one as they come. In fact, if the returned stream is infinite, choosing Flux<T> is very important as the other one will never complete.

Mono<List<T>> will emit zero or maximal one list of item of type T.
Flux<T>will emit zero or many items of type T
Momo wraps is bounded and Flux is not.
Mono<List<T>> is a synchronized Flux
Mono and Flux are both a Reactor implementation of a Publisher interface specified in a Reactive Stream Specification.
Reactor Mono class:
public abstract class Mono<T> implements Publisher<T> {...}
Reactor Mono class:
public abstract class Flux<T> implements Publisher<T> {...}
Flux could not be a rest api response.
Of course Fluxcan be used as response type of REST API. By using Flux as return type you can easily switch from asynchronous to synchronous processing . If you use Spring Boot you can even stream data to your consumer just by changing the Content-Type of you API endpoint to application/stream+json as mention by #Brian.
Note that Flux and Mono are non blocking which means that you working threads (computer resources) can be used more efficiently.

Related

How to access to request body using WebFlux and Netty HttpClient

I need to calculate some kind of digest of the request body using the WebClient of Webflux and this digest must be set into a HTTP header. Using the good old Spring MVC ClientHttpRequestInterceptor is easy because the request body is provided as an array of bytes.
The ExchangeFilterFunction does not provide access to the request body.
The body is sent as JSon and Spring uses Jackson in order to serialize Java objects, so an option could be serialize my Object into Json and calculate the digest on it, but this strategy has two drawbacks:
my code would repeat what Spring will do when the request is actually sent
there's no guarantee that the acutal bytes sent by Spring as a request are equal to what I've passed to the digest function
I suppose that I should use some low level API of Netty, but I can't find any example.
I implemented the solution proposed by #rewolf and it worked, but I encountered an issue because of the multi-threading nature of WebFlux.
In fact, it's possible that the client request is saved into the thread-local map by one thread, but a different thread tries to get it, so a null value is returned.
For example, it happens if the request to be signed is created inside a Rest controller method which has a Mono as a request body parameter:
#PostMapping
public String execute(#RequestBody Mono<MyBody> body){
Mono<OtherBody> otherBody = body.map(this::transformBodyIntoOtherBody);
...
webClient.post()
.body(otherBody)
.exchange();
...
}
According to Reactor specs, the Reactor Context should be used instead of Thread Local.
I forked #rewolf project and implemented a solution based on Reactor Context: https://github.com/taxone/blog-hmac-auth-webclient
This is not currently easy to do with WebClient. But there are ways to do so by intercepting the body post-serialization. This can be done by registering a custom encoder that intercepts the data after encoding, and the passes it to a custom HttpConnector to inject it as a header.
This blog post explains one way to achieve it: https://andrew-flower.com/blog/Custom-HMAC-Auth-with-Spring-WebClient
Edit: Currently this blog post doesn't take into account concurrent requests. See the accepted answer by Claodio for the modified approach.

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.)

wcf deserializing without memory allocations

I have a WCF service handling a very large number of requests (thousands per second). Each request contains objects, so they get built inside the DataContractSerializer during deserialization. My service processes the messages, and they get cleaned up by the .net garbage collector.
The problem is that garbage collections are causing problems for my service (requests occasionally taking 100+ milliseconds longer than they should). I need to minimize them. So I am looking for a way of using object pooling. In other words, I want the data contract serializer to obtain an object from my object pool (instead of getting one via GetUninitializedObject), and then when I am done processing the message, I would release it back to the pool for cleaning & reuse, thereby avoiding thousands of memory allocations a second.
I've seen this is possible with protobuf-net (Using protobuf-net, is it possible to deserialize a message without allocating memory?) and in fact I'm using protobuf elsewhere, but for this particular situation that is not an option
The DataContractSerializer is sealed and cannot be updated. So unfortunately you would not be able to remove it's call to FormatterServices.GetUninitializedObject.
What you will have to do instead is create your own serializer inheriting from XmlObjectSerializer so that you can fully control instance creation.
The next step is to create a DataContractSerializerOperationBehavior and override the CreateSerializer methods to return your customized serializer.
Last thing to do is remove the default DataContractSerializerOperationBehavior from the endpoint and replace it with the custom one that implements your custom serializer. Carlos Figueira has a post on his blog showing exactly how to do this (go to the section called Real world scenario: using a new serializer).

Serializing Delegates in WCF Using a Surrogate?

I have an idea, but I need help implementing it.
WCF does not support delegates in its contracts.
Instead it has a cumbersome callback contracts mechanism, and I'm looking for a way to overcome this limitation.
I thought about using a IDataContractSurrogate to replace each delegate in the contract with a token that will be serialized to the remote endpoint. There, the token will be deserialized into a generated delegate. This generated delegate will send a generic callback message which encapsulates all the arguments (that the delegate was invoked with).
The generic callback message will reach the first endpoint, and there the original delegate would be invoked with the arguments.
Here is the purposed (simplified) sequence:
A calls B-proxy.Foo(callback)
callback is serialized through a DelegateSurrogate.
The DelegateSurrogate stores the delegate in a dedicated delegate storage and replaces it with a token
The message arrives to B's endpoint
the token is deserialized through a DelegateSurrogate
The DelegateSurrogate constructs a generated delegate
B.Foo(generatedCallback) is invoked
Later, B is invoking generatedCallback(args)
generatedCallback(args) calls a dedicated generic contract on A's endpoint: CallbackContract-proxy.GenericCallback(args)
CallbackContract.GenericCallback(args) is invoked on A's endpoint
The original callback is retrieved from the storage and is invoked: callback(args)
I have already implemented this previously using service bus (NServiceBus), but I want to adapt the idea to WCF and I'm having hard time. I know how to implement steps 3,6,9 and 11. I don't know yet how to wire everything in WCF - especially the surrogate part.
That's it - I hope my question made sense, and that the collective wisdom here will be able to help me build this up.
Here's a sample usage for my desired solution:
// client side
remoteSvc.GetEmployeeById(17, emp =>
{
employees.Add(emp);
logger.log("Result received");
});
// server side
public void GetEmployeeById(int id, Action<Employee> callback)
{
var emp = getEmpFromDb(id);
callback(emp);
}
Actually, in this scenario I would look into the Expression API. Unlike a delegate, an Expression can be deconstructed at runtime. You can't serialize them by default, but a lot of work has been done in that space. It is also a bit like what a lot of LINQ providers do in the background, for example WCF Data Services.
Of course, another approach is simply to use a lambda expression as the hook for RPC, which is what I describe here. The code that implements this is freely available in the protobuf-net tree. You could customize this by using an attribute to associate your token with the method, and obtain the attribute from the MethodInfo.
IMO, the problem with delegates is that they are too tightly coupled to the implementation, so you can't have different implementations at each end (which is a common requirement).
Expressions have the advantage that lambdas still support intellisense etc, so you can do things like:
client.Invoke(svc => svc.Foo(123, "abc"));
and from that obtain Foo (the MethodInfo), 123 and "abc" separately, including captured variables, ref/out, etc. It all works.

Using Reqest / Response classes on a WCF contract - is that a good idea?

We have a situation where we might want to pass client information on every call we make on a WCF operation. At the response level, we want to have fields to indicate success and an error message.
Is it a good idea to use a Request class and a Response class? I was looking into two operation
OpeationResponseData Operation(OperationRequestData input);
I don't use OpeationRequest because that has issues with wsdl.
I will have base classes that will have the common fields each operation will need.
For example:
OperationResonseData : Response
OperationRquestData : Request
Another option is to use
Request<T> and Response<T>
I was wondering if there were a better way, or if there were some guidelines on this issue...
WCF's base messaging architecture, the Message class, already has support for all of these concepts built in.
For information that is supposed to be passed with each logical operation, you use headers.
For errors you throw FaultException or, if you want to return a custom data structure with your error, you throw FaultException. Being that errors result in faults, the lack of a fault indicates success. If you want to return details about your success then your operation should return a custom data type, otherwise you can just return void.
How this maps to what's sent across the wire depends on what formatting stack you're using (SOAP, REST, etc.). The default stack is SOAP and, being the blueprint for WCF, has a very natural mapping: headers map to SOAP headers and faults map directly to SOAP faults. For REST headers can be mapped as HTTP headers and faults would result in a 500 status with a message.