异步API设计客户端

时间:2017-08-17 15:40:25

标签: java spring rest api

假设我在Spring MVC中使用Java 8的完整性创建了一个异步REST API。

如何在客户端调用?如果它是非阻塞的,端点在处理之前是否会返回一些内容?即

@RequestMapping("/")  //GET method
public CompletableFuture<String> meth(){
   thread.sleep(10000);  
   String result = "lol";
   return CompletableFuture.completedFuture(result);
}

这是如何运作的? (上面这段代码只是我想到的随机编码)。

当我从google chrome @ localhost:3000/发送GET请求时会发生什么?我是异步API的新手,想要一些帮助。

3 个答案:

答案 0 :(得分:2)

不,客户不知道它是异步的。它必须正常等待结果。它只是服务器端,可以从释放工作线程来处理其他请求中获益。

答案 1 :(得分:1)

在这个版本中,它毫无意义,因为CompletableFuture.completedFuture()会立即创建一个完整的Future。

但是,在更复杂的代码中,您可能会返回尚未完成的Future。 Spring将不会发送响应正文,直到其他线程在complete()上调用Future

为什么不使用新线程?好吧,你可以 - 但在某些情况下,它可能更有效率。例如,您可以将任务放入Executor以由一小段线程处理。

或者您可以触发JMS消息,要求由完全独立的计算机处理请求。程序的另一部分将响应传入的JMS消息,找到相应的Future并完成它。在另一个系统上完成工作时,不需要专用于此HTTP请求的线程处于活动状态。

很简单的例子:

 @RequestMapping("/employeenames/{id}") 
 public CompletableFuture<String> getName(@PathVariable String id){
     CompletableFuture<String> future = new CompletableFuture<>();

     database.asyncSelect(
         name -> future.complete(name),
         "select name from employees where id = ?",
         id
     );

     return future;
  }

我在这里为异步数据库客户端发明了一个似是而非的API:asyncSelect(Consumer<String> callback, String preparedstatement, String... parameters)。关键是它会触发查询,然后不会阻止等待DB响应的步骤。相反,它会留下一个回调name -> future.complete(name)),供DB客户端在可以的时候调用。

这不是关于改进API响应时间 - 在我们提供有效负载之前,我们不会发送HTTP响应。这是关于更有效地使用服务器上的资源,以便在我们等待数据库响应时它可以做其他事情。

asynch REST有一个相关但不同的概念,其中服务器使用202 Accepted响应并使用类似Location: /queue/12345的标头,允许客户端轮询结果。但这不是你问的代码所做的。

答案 2 :(得分:0)

Java引入了

CompletableFuture 来处理复杂的异步编程。它允许程序员组合并级联异步调用,并提供静态实用程序方法runAsync和supplyAsync来抽象出手动创建线程。

这些方法默认情况下将任务分派给Java的公共线程池,或者作为可选参数提供自定义线程池。

如果端点方法返回CompletableFuture且从未调用#complete,则请求将一直挂起,直到超时为止。