我使用DropWizard创建了一个POST端点。
@POST
@Timed
public String runPageSpeed(@RequestParam String request) {
try {
JSONObject requestJSON = new JSONObject(request);
JSONArray urls = requestJSON.getJSONArray("urls");
process(urls); // this takes around 10 minutes to complete
return "done";
} catch (Exception e) {
throw new WebApplicationException("failed", Response.Status.INTERNAL_SERVER_ERROR);
}
}process(urls);大约需要10分钟才能完成,所以如果我们调用这个端点,需要超过10分钟才能得到响应。
我希望process(urls);在接收到来自请求的URL后在后台运行,并立即向用户返回一个响应。
我使用线程尝试了以下代码:
@POST
@Timed
public String runPageSpeed(@RequestParam String request) {
try {
JSONObject requestJSON = new JSONObject(request);
JSONArray urls = requestJSON.getJSONArray("urls");
Thread thread = new Thread() {
public void run() {
process(urls); // this takes around 10 minutes to complete
}
};
thread.start();
return "done";
} catch (Exception e) {
throw new WebApplicationException("failed", Response.Status.INTERNAL_SERVER_ERROR);
}
}这是可行的,但是如果我使用这种方法,特别是在大容量的情况下,有什么问题吗?
发布于 2017-09-20 21:57:12
DropWizard用户应该促进使用CompletableFuture进行异步处理,因为它是处理后台处理最安全的方法。使用CompletableFuture,您可以将重量级任务移动到后台线程,并同时继续轻量级任务,从而也可以向客户端发送响应。
@POST
@Timed
public String runPageSpeed(@RequestParam String request) {
try {
JSONObject requestJSON = new JSONObject(request);
JSONArray urls = requestJSON.getJSONArray("urls");
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
// perform heavyweight task
process(urls); // this takes around 10 minutes to complete
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// perform lightweight task
return "done";
} catch (Exception e) {
throw new WebApplicationException("failed",
Response.Status.INTERNAL_SERVER_ERROR);
}
}CompletableFuture在各个方面都有帮助,无论是将第一个复杂任务的返回值转换为第二个函数,还是使用它提供的各种各样的方法来通知失败。
runAsync()supplyAsync()thenApply()thenAccept()thenRun()exceptionally()handle()您还可以使用thenCompose()和thenCombine()链接thenCompose()和thenCombine(),这是在一个任务依赖其他任务时使用的。
https://stackoverflow.com/questions/46284266
复制相似问题