Why is Spring KafkaTemplate implemented in an asynchronous way? - spring

Why is Spring KafkaTemplate implemented in an asynchronous way? Do we have any other Spring implementation of it that is synchronous? I don't want to use futureTask.get() to make is seem synchronous

You probably miss the fact that Spring for Apache Kafka is nothing more than convenient Spring-friendly API around standard Kafka Client. And that's already a Producer.send() API to return for us a Future making all the stack as asynchronous. So, even if someone would do a synchronous API for you it still would do that futureTask.get() underneath.

Related

How to design reactive microservices, which have external blocking API calls?

I have some microservices, which should work on top of WebFlux framework. Each server has own API with Mono or Flux. We are using MongoDB, which is supported by Spring (Spring Data MongoDb Reactive).
The problem is external blocking API, which I have to use in my system.
I have one solution. I can just wrap blocking API calls in dedicated thread pool and use it with CompletableFuture.
Is there anything else to solve my problem? I think, that brand new Rsocket cannot solve my problem.
1.If possible, you can change your blocking API call to the reactive way using the WebClient class.
References:
Reference guide
WebClient API
A simple, complete sample
2.If the blocking API can't be changed to reactive ones, we should have a dedicated, well-tuned thread pool and isolate the blocking code there.
There is also an example here.
I don't see why you cannot wrap a blocking API call in a Flux or a Mono. You can also integrate Akka with Spring if the actor model seems easier to you.
RSocket should be a perfect fit, good tutorials to get you started
https://www.baeldung.com/spring-boot-rsocket
https://spring.io/blog/2020/04/06/getting-started-with-rsocket-spring-boot-channels

Does Spring Boot with its Blocking IO really fit well with Microservices?

There are a lot of tutorials and articles (including official site) promoting spring boot as a good tool for building microservices.
Let's say we have some rest api endpoint (User profile) which aggregates data from multiple services (User service, Stat service, Friends service).
To achieve this, user profile endpoint makes 3 http calls to those services.
But in Spring, requests are blocking and as I see, the server will quickly run out of available resources (threads) to serve request in such system.
So to me, it as quite inefficient way to build such systems (compared to non-blocking frameworks, like play! framework or node.js)
Do I miss something?
P.S.: I do not mean here spring 5 with its new webflux framework.
No one prevents you from building an asynchronous microservice architecture with Spring Boot :).
Something along these lines:
Instead of one service calling another synchronously, a service can put events to a queue (e.g. RabbitMQ). The events are delivered to services that subscribe to those events.
Using RabbitMQ and its "exchange" concept, the event producing service doesn't even need to the consumers of its events.
A blog post detailing this with Spring Boot code can be found here: https://reflectoring.io/event-messaging-with-spring-boot-and-rabbitmq/
This is not a limitation of Spring rather it is more to do with the Application Architecture.
For instance, the scenario that you have is commonly solved using Aggregate Design Pattern
While this solution is quite prevalent,it has the limitation of being synchronous, and thus blocking. Asynchronous behaviour in such scenarios should be implemented in an application specific way.
Having said that if you have to call other services in order to be able to serve a response to a request from a client(outside), this is typically an architectural problem. It really doesn’t matter if you are using HTTP or asynchronous message passing (with a request-reply pattern), the overall response time for the outside client will be bad
Also, I have seen quite a few applications which uses synchronous REST calls for external clients, but when communication is needed between internal MicroServices, it should always be asynchronous. You can read an interesting paper on this topic here MicroServices Messaging Patterns

WebClient vs RestTemplate

As per spring 5:
WebClient is an interface representing the main entry point for performing web requests.
It has been created as a part of the Spring Web Reactive module and will be replacing the classic RestTemplate in these scenarios. The new client is a reactive, non-blocking solution that works over the HTTP/1.1 protocol
Does that mean, we need to recode for the old applications using RestTemplate if we want to upgrade to Spring 5?
Or there is some workaround to work with RestTemplate in Spring 5?
No, RestTemplate will continue to exist (at least for now). You don't have to replace it with WebClient.
One of the main differences is RestTemplate is synchronous and blocking i.e. when you do a rest call you need to wait till the response comes back to proceed further.
But WebClient is complete opposite of this. The caller need not wait till response comes back. Instead he will be notified when there is a response.
If you need such a functionality, then yes you need to replace your Resttemplate with WebClient.
You can in fact achieve Rest template like synchronous processing in webclient using .block(). But the other way is not possible.
EDIT:
RestTemplate will be deprecated in a future version(> 5.0) and will not have major new features added going forward
According to the Java Doc the RestTemplate will be in maintenance mode. Spring team advise to use the WebClient if possible:
NOTE: As of 5.0, the non-blocking, reactive
org.springframework.web.reactive.client.WebClient offers a modern
alternative to the RestTemplate with efficient support for both sync
and async, as well as streaming scenarios. The RestTemplate will be
deprecated in a future version and will not have major new features
added going forward.
RestTemplate is not really deprecated. But it will not be evolved in the future. So sticking to RestTemplate is perfectly valid if it does what you need.
Another way to put that is that if you need specific usage patterns like streaming, scatter/gatter, or custom timeouts, this won't be covered by RestTemplate and you need to use WebClient instead.
Now using WebClient in a blocking application is fine too. Using block() shouldn't hurt there and Spring MVC controller does partially support reactive return types.
WebClient is Non-Blocking Client, RestTemplate is Blocking Client.
For a long time, spring serves as a web customer. Under the hood, RestTemplate uses the Java API API, which is based on the subject model.This means that the matter will be blocked until the client receives a response. The problem with the blockage code is due to the existence of any string of memory and cpu cycles. Let us consider a lot of applications that are waiting for low services that are needed to produce the result.Sooner or later, requests for the results are collected. As a result, the program creates many issues, which result in depletion of a pool of thread or occupying all of the available memory. We can also experience performance performance due to the cpu switching.
Spring WebClient vs. RestTemplate
WebClient supports asynchronous as well as synchronous calls.
RestTemplate supports only synchronous calls.
No changes are required in old code even if the RestTemplate is depracated(as long as you don't need asynchronous behaviour)

Development compromises in using Spring Cloud Stream

The case for event-driven microservices such as Spring Cloud Stream is their asynchronous nature, which I do agree it makes them more scalable
But I have an issue regarding how to code it in a way where I don't lose certain key features that I have access to using synchronous services
In a servlet-based MS, I make full use of servlet context variables and servlet-based Spring autowiring functions
For e.g., I leverage heavily on HTTP headers to carry metadata between microservices without having to impact the payload. But in Spring Cloud Stream using Kafka, Kafka doesn't support message headers of any kind! I lose that immediately if I use SCS. Putting them into the payload causes all sort of changes in my model classes if I define the attributes clearly. Yes, I can use a simple Hashmap to simulate the HTTP header object but it really seems like reinventing the wheel to me.
On the auto-wiring side: I maintain an audit log record per request, which I implement by declaring a request-scoped Hashmap bean and autowiring it into any methods in the Servlet's call stack that needs to append data to the audit log. Basically it's just a global variable to hold some data within a single request. But in SCS, again, I lose that cos bean scopes that leverage on servlets are not available.
So far, there seems to be a lot of trade-offs that I have to make just to make Spring Cloud Stream work for me.
I thought about an alternative approach where I use SCS just to create an entry point but the Source method would just get the event, use a Processor to construct a HTTP request and send the request along to a HTTP endpoint. But, why go through all that trouble then?
Hoping that some more experienced devs would be able to shed some light on how they leverage on SCS.
#feicipet Thanks for the detailed question. let me try to address some of your concerns in the order you have listed them:
+1
+1
I am not sure why you are referring to it as servlet-based instead of Spring-based? Those are features provided by Spring, but read on. . .
Spring Cloud Stream doesn't use Kafka, the end user does while Spring Cloud Stream provides Kafka binder allowing Spring Cloud Stream to integrate with Kafka. Further more, while Kafka indeed did not support headers prior to version 0.11, Spring Cloud Stream always supported and will continue support headers even with Kafka pre-0.11, embedding them in the Message and then extracting them in the consumer side into the proper Message headers completely transparent to the end user. In other words one would assume that Kafka did support headers by simply using Spring Cloud Stream. With Kafka 0.11+ headers are supported natively and we have adjusted to that with the same level of transparency.
So, you don't need to put anything in the payload. Just create an appropriate Message<payload, headers> and SCSt will take care of the rest regardless of the broker (Kafka, Rabbit, Foo etc.).
Yes you do simply due to the fact that as you eluded earlier SCSt promotes an asynchronous and stateless architecture. However, I do not agree that what you are trying to accomplish is un-accomplishable. Rather it is accomplishable the way you are describing, but there are other way to maintain context and I would be more then glad to discuss it as a separate topic.
I would not call them trade-offs, rather difference in the architecture, that has its benefits, but it is a not one-size-fits-all architecture and therefore its viability should be discussed within the context of a concrete use case.
+1. You don't have to separate it as Source and Processor. You can simply create a custom Source app with exposed REST endpoint and custom processing logic. However we are currently working on enhancements i the framework to ensure that you could do the same with the existing starter apps.
Obviously we have touched on many points here and some of them would probably need to be debated further, but I hope this clears up some of your concerns.
Cheers

Spring JavaMailSender: Making it asynchronous and persistent

Is there an easy/lightweight way to add persistence to Spring's JavaMailSender and have it operate asynchronously? Does Spring provide any "built-in" support for this? I'm currently looking at queues with JMS, but they seem like overkill for the task at hand (looking at ActiveMQ and RabbitMQ). Is there a lightweight JMS option?
Your approach with jms is fine. Unfortunately persistence and asynchronous processing is not such a simple task and you will have to code a bit.
However have a look at Spring integration, it provides built-in support for JMS inbounds and e-mail outbounds - all you have to do is connect the pieces via XML DSL.
If you want to make any method in Spring asynchronous, all you need to do is configure task namespace in the xml config via <task:annotation-driven/>. Then, you just annotate the method with #Async and it will run in its own thread. Note that an async call will run in its own transaction, as Spring grabs a new thread from its internal pool to service the call. If you do this, then you don't need JMS for aynchronous processing.

Resources