When using Netbeans and writing an arbitrary REST endpoint, NetBeans always displays a warning that the method can be converted to asynchronous.
For example, I create the following method:
@GET
@Path("/test")
public String hello() {
return "Hello World!";
}
NetBeans then shows a warning, see below:
Clicking on the tooltip generates this code:
private final ExecutorService executorService = java.util.concurrent.Executors.newCachedThreadPool();
@GET
@Path(value = "/test")
public void hello(@Suspended final AsyncResponse asyncResponse) {
executorService.submit(new Runnable() {
@Override
public void run() {
asyncResponse.resume(doHello());
}
});
}
private String doHello() {
return "Hello World!";
}
The same holds true when creating a PUT or POST method. Since NetBeans always shows a warning when a REST endpoint is implemented, this tells me that writing synchronous endpoints is considered wrong/bad practice. So, should every REST endpoint be asynchronous? Why?
REST clients can be implemented either synchronously or asynchronously. Both MicroProfile Rest Client and JAX-RS can enable asynchronous clients. A synchronous client constructs an HTTP structure, sends a request, and waits for a response.
For others, the client may need a response, but can't get it in the original request because of the long processing time, like if they are generating a complex report. This requires pulling the relevant data together and rendering a PDF, which can be a time-consuming process, often better performed asynchronously.
Synchronous/asynchronous APIs are application programming interfaces that return data for requests either immediately or at a later time, respectively. Synchronous/asynchronous APIs provide a way to make immediate or scheduled requests for resources, data or services when available.
Synchronous/asynchronous APIs are application programming interfaces that return data for requests either immediately or at a later time, respectively. Asynchronous requests are useful in maintaining functionality in an application rather than tie up application resources waiting on a request.
Sync
- The work is done in the same thread as the IO. All threads are in the same pool.
- Accepting a request takes 100 ms; doing the work takes 900 ms; total 1 s.
- If you want to be able to accept 100 requests / second you need 100 IO threads.
- If you want to be able to fulfill 100 requests / second you need the same 100 IO threads.
Async
- The work is done in a different thread than the IO. You have two different thread pools.
- Accepting a request still takes 100 ms; total 100 ms.
- If you want to be able to accept 100 req/s you only need 10 IO threads in your pool.
- Work still takes 900 ms; total 900 ms.
- If you want to be able to fulfill 100 requests / second you need 90 Worker threads.
The initial number of threads in both scenarios is the same, yes.
However, IO threads and Worker threads usually have different requirements:
For a simple app it doesn't really matter if you make your endpoints sync or async; but in the general case, with a decent number of requests per second and different tasks with different traits (processing time, need of spawning their own child threads, priority), making your endpoints asynchronous is the best way to have a highly responsive system while making an efficient use of resources.
There are two main dimensions to service performance, from the client's perspective. A service client cares about:
Throughput, that is how many concurrent requests can your service handle?
Latency, that is how long does one request have to wait before it gets a response?
It's easy to be tempted to care about the throughput alone but at a certain point, trying to achieve throughput will start to negatively affect latency. Multithreading isn't free at some scale.
The Netbeans hint will help only with throughput, but like you've deduced, it does nothing to help with latency - that's entirely on you, bud. If throughput isn't a concern for your application at this point, you can safely ignore the hint.
There's no requirement or even rule of thumb that all JAX-RS services be async, that's just a leap on the part of Netbeans development team (a pretty confident leap too, considering this is one hint they didn't think we'd ever need to disable.
Jersey does provide some recommendations to work around the limitations of latency but the fact remains that there's no magic to it: a server-side operation will take as long as it takes and the client doesn't have a choice but to wait for it to complete, barring the implementation of some call-back pattern.
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