2017-08-05 237 views
0

我有2個微服務(A和B)。異步HTTP請求與新線程上的HTTP請求

A有一個接受POST請求的端點。當用戶發出POST請求時,會發生以下情況:

  1. 服務A從POST請求正文獲取對象並將其存儲在數據庫中。
  2. 服務A將對象轉換爲不同的對象。新對象通過Jersey HTTP客戶端發送到服務B.

第2步發生在我創建的Java線程池(Executors.newCachedThreadPool)上。通過在新線程上執行第2步,服務A的端點響應時間不受影響。

但是,如果服務B需要很長時間才能響應,則服務A在接收到許多POST請求時可能會創建太多線程。爲了解決這個問題,我可以使用一個固定的線程池(Exectuors.newFixedThreadPool)。

除了固定線程池,我還應該使用異步非阻塞HTTP客戶端嗎?如這裏的一個:https://hc.apache.org/httpcomponents-asyncclient-dev/。我使用的Jersey HTTP客戶端被阻塞。

這似乎是正確的使用異步HTTP客戶端。 但是,如果我切換到一個固定的線程池,我認爲異步HTTP客戶端不會提供顯着的好處 - 我錯誤地認爲這是什麼?

回答

0

即使你使用固定的線程池所有在它的線程將被阻止在第2步的意思,他們不會做任何有意義的工作 - 只是等待你的API返回這不是一個務實的迴應資源管理。在這種情況下,您將能夠處理有限數量的傳入請求,因爲線程池中的線程將始終處於繁忙狀態,而不是處理新的請求。

對於非阻塞客戶端,您僅阻塞一個負責發送和等待所有請求/響應的單線程(我們稱之爲分派器線程)。它將在一個「while循環」(你可以稱之爲一個事件循環)中運行,並檢查是否所有的包都作爲響應接收,以便它們準備好接收工作線程。

在後一種情況下,您將獲得大量的可用線程準備好執行一些有意義的工作,因此您的吞吐量將會增加。

0

區別在於,對於同步客戶端,步驟A線程將連接到步驟2端點並等待響應。使步驟2實現異步將直接返回200(或其他)將有助於減少等待時間;但它仍然會在連接並等待響應。

如果使用非阻塞客戶端,則步驟A調用本身將由另一個線程完成。所以一切都從步驟A線程解開。另外,系統可以利用該線程處理其他內容,直到獲得步驟B的響應並需要恢復工作。

這個想法是,你的起源線程不會空閒很長時間等待響應,而是被重用來在其間做其他工作。

0

使用非阻塞HTTP客戶端的原因是爲了防止在線程切換時使用太多的CPU。如果您已經通過限制後臺線程的數量來解決該問題,那麼非阻塞IO將不會提供任何明顯的好處。

您的設置存在另一個問題:它很容易受到DDOS攻擊(有意或無意的攻擊)。如果某人經常打電話給您的服務,它將在內部創建一個巨大的工作負載,以保持服務很長時間的忙碌。您肯定需要限制後臺任務隊列(這是Executor類的支持功能),並且如果有太多未決任務,則返回503(或等效項)。