Dropwizard中的JAX-RS:处理具有即时响应的异步调用 [英] JAX-RS in Dropwizard: Handling async call with immediate response

查看:84
本文介绍了Dropwizard中的JAX-RS:处理具有即时响应的异步调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个资源 Class ,带有 @ManagedAsync 方法的类,如下所示:

I have a Resource Class, with a @ManagedAsync method Class which looks like this:

@Path("my-resource")
public class MyResource extends BaseResource{

    private DatumDAO datumDAO;

    public MyResource(DatumDAO datumDAO){
        this.datumDAO = datumDAO;
    }

    public void cleanDatum(Datum datum){
       //time taking operations
    }

    @GET
    @ManagedAsync
    @Path("/cleanup/{from}/{till}/")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @UnitOfWork
    public void cleanupDirtyData(@Suspended final AsyncResponse asyncResponse, @PathParam("from") DateTimeParam from,
            @PathParam("till") DateTimeParam till) throws IOException{

        logger.debug("will try to cleanup dirty data in range: " + from + " " +  till);
        List<Datum> data = datumDAO.getALlDirtyDatumInRange(from.get().toDate(), till.get().toDate());
        Map<Long,String> cleanupMap = new HashMap<Long,String>();
        for(Datum datum: data){
            cleanDatum(datum);
            cleanupMap.put(datum.getId(), "cleaned");
        }
        // this response need to be sent [can be ignored]       
        asyncResponse.resume(Response.status(HttpStatus.OK_200).entity(cleanupMap).build());

    }

}

自通话以来 cleanupDirtyData 可能要花一些时间,我不希望客户端完全等待它,我知道执行工作已分流到另一个工作线程。

Since the call to cleanupDirtyData can take a while, I don't want clients to wait for it completely, I understand that execution work is offloaded to a different worker thread.

我要实现的目标是立即响应客户端并继续异步执行功能 cleanupDirtyData

What I am trying to achieve is to give an immediate response to the client and keep doing execution of the function cleanupDirtyData asynchronously.

因此尝试了以下操作:

设置强制超时并过早对客户端的响应,但这似乎不是理想的方法,它会停止执行。

Putting a forceful timeout, and giving a premature response to the client, but that doesn't seem to be the ideal way and it stops the execution.

看起来像这样:

@Path("my-resource")
public class MyResource extends BaseResource{

    private DatumDAO datumDAO;

    public MyResource(DatumDAO datumDAO){
        this.datumDAO = datumDAO;
    }

    public void cleanDatum(Datum datum){
       //time taking operations
    }

    @GET
    @ManagedAsync
    @Path("/cleanup/{from}/{till}/")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @UnitOfWork
    public void cleanupDirtyData(@Suspended final AsyncResponse asyncResponse, @PathParam("from") DateTimeParam from,
            @PathParam("till") DateTimeParam till) throws IOException{

        // Register handler and set timeout
        asyncResponse.setTimeoutHandler(new TimeoutHandler() {
            public void handleTimeout(AsyncResponse ar) {
                asyncResponse.resume(Response.status(SERVICE_UNAVAILABLE).entity(
                    "Operation timed out -- please try again").build());                    
                }
        });
        ar.setTimeout(15, TimeUnit.SECONDS);      

        logger.debug("will try to cleanup dirty data in range: " + from + " " +  till);
        List<Datum> data = datumDAO.getALlDirtyDatumInRange(from.get().toDate(), till.get().toDate());
        Map<Long,String> cleanupMap = new HashMap<Long,String>();
        for(Datum datum: data){
            cleanDatum(datum);
            cleanupMap.put(datum.getId(), "cleaned");
        }
       // this response need to be sent [can be ignored]              
        asyncResponse.resume(Response.status(HttpStatus.OK_200).entity(cleanupMap).build());

    }

}


推荐答案

JAX-RS异步服务器API 容器如何管理请求有关。但它仍会保留请求,不会影响客户体验。

The JAX-RS Asynchronous Server API is all about how the container will manage the request. But it will still hold the request and won't affect the client experience.

引用Jersey文档中的异步服务器API

Quoting the Jersey documentation about the Asynchronous Server API:


请注意,使用服务器端异步处理模型不会改善
的请求客户感知的处理时间。但是,通过释放
初始请求处理线程回到I / O容器,
会增加服务器的吞吐量,而
请求可能仍在队列中等待处理或
处理可能仍在另一个专用线程上运行。
发布的I / O容器线程可用于接受和处理新的
传入请求连接。

Note that the use of server-side asynchronous processing model will not improve the request processing time perceived by the client. It will however increase the throughput of the server, by releasing the initial request processing thread back to the I/O container while the request may still be waiting in a queue for processing or the processing may still be running on another dedicated thread. The released I/O container thread can be used to accept and process new incoming request connections.

如果要立即给客户答复,您可能正在寻找类似的东西:

If you want to give the client an immediate response, you may be looking for something like:

@Singleton
@Path("expensive-task")
public class ExpensiveTaskResource {

    private ExecutorService executor;

    private Future<String> futureResult;

    @PostConstruct
    public void onCreate() {
        this.executor = Executors.newSingleThreadExecutor();
    }

    @POST
    public Response startTask() {
        futureResult = executor.submit(new ExpensiveTask());
        return Response.status(Status.ACCEPTED).build();
    }

    @GET
    public Response getResult() throws ExecutionException, InterruptedException {
        if (futureResult != null && futureResult.isDone()) {
            return Response.status(Status.OK).entity(futureResult.get()).build();
        } else {
            return Response.status(Status.FORBIDDEN).entity("Try later").build();
        }
    }

    @PreDestroy
    public void onDestroy() {
        this.executor.shutdownNow();
    }
}



public class ExpensiveTask implements Callable<String> {

    @Override
    public String call() throws Exception {

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "Task completed";
    }
}

在servlet容器中,可以使用 ExecutorService 运行您的昂贵任务。在Java EE容器中,应考虑 ManagedExecutorService

In a servlet container, you can use an ExecutorService to run your expensive task. In a Java EE container, you should consider a ManagedExecutorService.

这篇关于Dropwizard中的JAX-RS:处理具有即时响应的异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆