问题
I am building Mobile backend API using Java EE - JAX-RS 2.0 technology.
Since most of mobile client consumes are asynchronous http calls
so my question is: Should I use asynchronous feature for all JAX-RS resources? And the reason if not?
The below is the template Mobile Async API
@Path("/async_api")
public class AsyncResource {
@GET
@Path("/loadUsers")
@Produces(MediaType.APPLICATION_JSON)
public void loadUsers(@Suspended AsyncResponse asyncResponse) {
//TODO: ManagedExecutorService
new Thread(new Runnable() {
@Override
public void run() {
List users = loadBigUsers();
asyncResponse.resume(users);
}
private List loadBigUsers() {
return null; // Return big list
}
}).start();
}
}
Thank you!
回答1:
In JAX-RS the @Suspend
annotation and AsyncResponse
are needed only in certain typical scenarios. The first scenario was already identified in your code example. It is long running tasks. In this case the AsyncResponse
can be used to execute long running code in a background thread. While this would not make sense at the first glance we need to think about how an application server / container handles its requests. Usually there is a pool of threads that accepts and handles client requests. If you implement expensive operations inline in your JAX-RS service methods one of the threads in the pool is blocked for the entire runtime. With the AsyncResponse
the executor thread gets returned to the pool and other requests can be served in parallel.
@Path("/users")
public class UserRestService {
@GET
public void getAllUsers(@Suspend final AsyncResponse asyncResponse) {
new Thread(new Runnable(
@Override
public void run() {
List<Users> users = UserDAO.loadAllUsers();
asyncResponse.resume(users);
}
) {}).start();
}
}
The second application scenario for AsyncResponse
is the often seen pattern of producer consumer patterns. Assuming you have a queue bound to the URL https://yourservice.at/queue/next
then a @GET
method can be used for a blocking take()
on lets say a LinkedBlockingQueue
. On the same URL you could bind a @POST
method which adds data to the queue. In this case you would wrap up the functionality with the take()
operation in an AsyncResponse
.
@Path("/queue/next")
public class MessageQueueService {
private static final LinkedBlockingQueue<AsyncResponse> suspendedResponses = new LinkedBlockingQueue<AsyncResponse>();
@GET
public void getNextMessage(@Suspend final AsyncResponse asyncResponse) {
MessageQueueService.suspendedResponses.put(asyncResponse);
}
@POST
public void putNewMessage(final String message) throws InterruptedException {
AsyncResponse asyncResponse = suspendedResponses.take(); // note how this could also block a thread
asyncResponse.resume(message);
}
}
From these explanations you can also see, that the JAX-RS @Suspended
mechanism is used to create an asynchronous server side task. Whether or not the same request is also executed in an asynchronous manner on the client is a whole different story.
来源:https://stackoverflow.com/questions/36214112/should-we-always-use-asynchronous-jax-rs-resources-for-mobile-backend