I have a api(GET REST) developed using java & Quarkus. I want to understand the default mechanism on how this api handle the multiple requests to same api. Is there any queuing mechanism used by default.? is there any multithreading used by default?
Please help to understand this.
Quarkus
became popular for it's optimization of resources and benchmarks on heavy loaded systems. It will by default use 2 kind of different threads.
I/O threads or otherwise called event-loop threads
Worker threads
I/O threads or otherwise called event-loop threads. Those threads are responsible, among other things, for reading bytes from the HTTP request and writing bytes back to the HTTP response. The important here is that those threads are usually not blocked at all. You can see a simple of the functionality of those threads as illustrated in the following picture
The number of those I/o
threads as described in documentation
The number if IO threads used to perform IO. This will be automatically set to a reasonable value based on the number of CPU cores if it is not provided. If this is set to a higher value than the number of Vert.x event loops then it will be capped at the number of event loops. In general this should be controlled by setting quarkus.vertx.event-loops-pool-size, this setting should only be used if you want to limit the number of HTTP io threads to a smaller number than the total number of IO threads.
Worker threads. Here a pool of threads again are maintained by the system and the system assigns a worker thread to a execute some scheduled work on some request. Then this thread can be used from another thread to execute some other task. These threads normally take over long running tasks or blocking code.
The default number of these type of threads are 20 if not otherwise configured as indicated by documentation
So to sum up a request in Quarkus
will be executed either by some I/O thread
or some Worker thread
and those threads will be shared between other requests too. An I/O thread
will normally take over non blocking tasks that do not take long to be executed. A Worker thread
will normally take over blocking tasks and long running processes.
Taking in consideration the above it makes sense that Quarkus
will have configured much more Worker threads
in the worker thread pool than I/O threads
in the i/o thread pool.
A worker thread will serve a specific request (ex request1) and if during this serve it get's blocked to do some I/O operation it will continue to wait for the I/O in order to complete the request it serves. When this request is finished the thread is able to move on and serve some other request (ex request2).
An I/O
thread or event-loop thread will serve a specific request (ex request1) and if during this serve it get's blocked for some I/O
operation which is needed for this request, it will pause this request, and continue to serve another request (ex request2). When the I/O
of first request is completed the thread will return according to some algorithm that schedules the job again to request1 to continue from where it was left.
Now someone may question what is the case then, since usually every request requires some type of I/O
operation then how can someone use I/O
thread to have better performance. In that case the programmer has 2 choices when he declares the controller of quarkus
to use I/O
thread:
Spawn manually inside the controller method which is declared to be I/O
some other thread to do the blocking code block work while the outer thread that serves the request is of type I/O
(read http request data, write http response). The manual thread can be of type worker inside some service layer. This is a bit complicated approach.
Use some external library for I/O
operations that's expected to work with the same approach that I/O
threads work in quarkus
. For example for database operations the I/O
could be operated by the library hibernate-reactive
. This way full benefits of I/O
approach can be achieved.
Considering that we are in the java ecosystem it will be very useful to also mention that the above architecture and efficiency of resources is similar (not exactly same) with Spring Reactive (Web Flux)
.
But quarkus
is based on Jax-Rs
and will by default provide this architecture of efficient use of resources, independently of whether you write reactive code or not. When using Spring Boot however in order to have a similar efficiency with quarkus
you have to use Spring Reactive
(Web Flux).
In case you use the basic spring boot web
, the architecture used will be of a single thread per incoming request. A specific thread in this case is not able to switch between different threads. It will need to complete some request in order to handle the next request.
Also in quarkus
making a controller method execute from an I/O
thread is as simple as placing an annotation @NonBlocking
in that method. The same for an endpoint method that needs to be executed from a worker thread with @Blocking
.
In Spring boot however switching from those 2 type of threads may mean switching from spring-boot-web
to spring-boot-webflux
and vice versa. Spring-boot-web
has some support however now with servlet-3
to optimize it's approach, article with such optimization, but this requires some programming optimization and not an out of the box functionality.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With