2017-08-18 23 views
-2

說我有我的API兩個端點(春如以前):比線程處理更多的連接

@RequestMapping("/async") 
public CompletableFuture<String> g(){ 
    CompletableFuture<String> f = new CompletableFuture<>(); 
    f.runAsync(() -> { 
     try { 
      Thread.sleep(5000); 
      f.complete("Finished"); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    }); 
    Thread.sleep(1000); 
    return f; 
} 

@RequestMapping("/sync") 
public String h() throws InterruptedException { 
    Thread.sleep(5000); 
    Thread.sleep(1000); 
    return "Finished"; 
} 

當我送2 GET請求(只是單一的GET請求):

​​- - >應答5024ms

localhost:8080/sync - >在「響應6055ms`

這是有道理的,因爲我們派出只是單個請求。現在事情變得有趣了,當我用Siege進行負載測試時,涉及到255個併發用戶。

在這種情況下,我的async API端點無法處理多個連接。

所以async是不可擴展的。

這是否取決於我的硬件?假設我有硬件能夠處理更多的線程處理程序,然後使用沉重的硬件,異步程序能夠處理更多的事務,因爲線程更多?

+0

還在工作呢,是吧? – Kayaman

+0

你有沒有例外?錯誤? – dit

+0

@Kayaman,它的好奇心;我對基礎設施感興趣,但無法找到足夠的信息。 – Bana

回答

0

您仍然在使用ForkJoinPool.commonPool()進行異步調用。我告訴你它很小,它會被填滿。試試這個(我修正了你的CompletableFuture代碼,因爲它完全錯了,它只是在你的例子中不顯示)。

CompletableFuture<Void> f = CompletableFuture.runAsync(() -> { 
     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    }, Executors.newSingleThreadExecutor()); 
return f; 

現在每個異步調用都有它自己的執行程序,所以它不會在公共池中窒息。當然,由於所有的異步調用都有自己的執行器,這是一個不好的例子。您希望使用共享池,但要比公共池大一些。

它與硬件沒有任何關係(很好,很少)。它與長時間運行操作混雜在一起,與短時間運行操作有關。

+0

謝謝!我一直在做更多的研究。但是,當我嚴重超載服務器(許多線程),我得到了「原生線程錯誤。」。什麼是解決這個問題的方法? – Bana

+0

通過創建更少的線程。服務器限制了常規的請求工作線程,但我的示例中的異步線程每次都會創建一個線程,正如答案中所述。 – Kayaman

+0

我用'newCachedPoolThread'創建了一個ExecutorService(做了一些研究),所以現在服務器做得很好。這是一個好方法嗎? – Bana