2017-08-17 162 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