我们是否应始终使用异步JAX-RS资源用于移动后端?
我正在使用Java EE构建Mobile后端API – JAX-RS 2.0技术。
由于大多数移动客户端消耗都是异步http调用
所以我的问题是: 我应该为所有JAX-RS资源使用异步function吗? 原因如果不是?
以下是模板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(); } }
谢谢!
在JAX-RS中,仅在某些典型场景中需要@Suspend
注释和AsyncResponse
。 您的代码示例中已经确定了第一个方案。 这是一项长期运行的任务。 在这种情况下, AsyncResponse
可用于在后台线程中执行长时间运行的代码。 虽然这在第一眼看上去没有意义,但我们需要考虑应用程序服务器/容器如何处理其请求。 通常有一个线程池接受和处理客户端请求。 如果在JAX-RS服务方法中内联实现昂贵的操作,则会为整个运行时阻塞池中的某个线程。 使用AsyncResponse
,执行程序线程将返回到池中,并且可以并行提供其他请求。
@Path("/users") public class UserRestService { @GET public void getAllUsers(@Suspend final AsyncResponse asyncResponse) { new Thread(new Runnable( @Override public void run() { List users = UserDAO.loadAllUsers(); asyncResponse.resume(users); } ) {}).start(); } }
AsyncResponse
的第二个应用场景是生产者消费者模式常见的模式。 假设你有一个绑定到URL https://yourservice.at/queue/next
的队列,那么@GET
方法可以用于阻塞take()
,例如LinkedBlockingQueue
。 在同一个URL上,您可以绑定一个@POST
方法,该方法将数据添加到队列中。 在这种情况下,您将使用AsyncResponse
的take()
操作来包装该function。
@Path("/queue/next") public class MessageQueueService { private static final LinkedBlockingQueue suspendedResponses = new LinkedBlockingQueue (); @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); } }
从这些解释中您还可以看到,JAX-RS @Suspended
机制用于创建异步服务器端任务。 在客户端上是否也以异步方式执行相同的请求是完全不同的故事。