我们是否应始终使用异步JAX-RS资源用于移动后端?

时间:2016-03-25 04:40:37

标签: java asynchronous jax-rs java-ee-7

我正在使用Java EE构建Mobile后端API - JAX-RS 2.0技术。

由于大多数移动客户端消耗都是异步http调用

所以我的问题是: 我应该为所有JAX-RS资源使用异步功能吗?如果没有原因?

以下是模板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();
    }
}

谢谢!

1 个答案:

答案 0 :(得分:5)

在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> users = UserDAO.loadAllUsers();
                asyncResponse.resume(users);
            }
        ) {}).start();
    }
}

AsyncResponse的第二个应用场景是生产者消费者模式常见的模式。假设您有一个绑定到网址https://yourservice.at/queue/next的队列,那么可以使用@GET方法来阻止take(),例如LinkedBlockingQueue。在同一个URL上,您可以绑定一个@POST方法,该方法将数据添加到队列中。在这种情况下,您将使用take()中的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);
    }
}

从这些解释中您还可以看到,JAX-RS @Suspended机制用于创建异步服务器端任务。在客户端上是否也以异步方式执行相同的请求是一个完全不同的故事。