2017-08-17 106 views
-1

假设我在Spring MVC中使用Java 8的Completeable创建异步REST API。异步API设计客户端

这是如何在客户端中调用的?如果其非阻塞,那么端点在处理之前是否返回一些东西?即

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

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

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

回答

2

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

+0

那么使用CompleteableFuture有什么意义,为什么不使用一个新的线程呢?那么这样就完全不会改善API响应时间? – Bana

+0

那么你会使用另一个线程。这是完成'CompletableFuture'并使结果被发送的那个。 – Kayaman

+0

那么当人们说Async改善API响应时间时,这意味着什么。到底如何? – Bana

0

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

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

如果某个端点方法返回了CompletableFuture,并且永远不会调用#complete,则该请求将挂起直至超时。

1

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

但是,在一段更复杂的代码中,您可能会返回尚未完成的Future。除非其他线程在此Future上调用complete(),Spring将不会发送响应主体。

为什么不只是使用一个新的线程?那么,你可以 - 但在某些情况下,它可能不会更有效。例如,您可以将一个任务放入一个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)。重点在于它会触发查询,然后不会阻止等待数据库响应。相反,它会为数据库客户端在可能时调用回调name -> future.complete(name))。

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


有一个相关的,但不同的概念非同步REST,其中服务器202 Accepted和像Location: /queue/12345头响应,允许客户端轮询结果。但这不是你询问的代码的作用。

+0

你能举一个返回未完成未来的例子吗?所有这些都改善了API响应时间是我的主要问题。 – Bana