2017-06-23 30 views
3

我們有一個相當高的吞吐量演員系統,它通過http進行異步調用外部系統。我們發現,由於他們從我們那裏收到的電話數量衆多,下游系統正在遭到不測。限制異步調用演員

使用由下游系統中的呼叫「管」在這裏描述的模式:https://petabridge.com/blog/akkadotnet-async-actors-using-pipeto/

之所以如此多的呼叫到下游系統做是因爲一個演員不會等待響應異步調用在它的郵箱中處理下一條消息之前返回(當異步調用被啓動時,它完成了消息)。顯然這是設計的,但在這種情況下,會導致對外部服務進行非常多的異步調用。

我們需要一種限制呼叫的方法。我可以想到解決這個問題的幾個可能的解決方案。

  1. 通過等待任務完成來同步執行對外部服務的調用。爲演員設置一個池路由器,這基本上是一種限制對這個外部服務進行調用的方式。

  2. 使用ReceiveAsync方法而不是Receive。這基本上是完全相同的選項1.在petabride頁我張貼以上雖然說這個這個方法 - 「只是不去做」 :)

  3. 使異步調用之前,開始積攢任何來電消息,然後在異步任務完成後取消它們。顯然使用這種方法的吞吐量要受限得多。

我想知道有沒有人在使用akka時有類似的問題,並能解決它?

編輯:

那麼它到底是隻爲我們的工作選項1。即有一個帶有Receive()的池路由器,該路由器專門等待IO調用所需的(調用外部系統的api)。這似乎工作得很好,我們可以通過設置池大小來控制'節流'。

我們嘗試了選項2(ReceiveAsync),但是我們發現在某些時候系統會停下來並停止響應而不會引發任何錯誤。我們懷疑它陷入了僵局。這可能是由於異步函數的工作方式,而只是使用.Wait()或.Result等待任務。我現在可以看到爲什麼Petabridge建議不要使用ReceiveAsync :)

我們沒有嘗試選項3,因爲這意味着更重要的更改。

回答

2

對於我來說,我已經解決了這個問題,它使用創建子路由器作爲工作者,一次只能處理一條消息。因此,您可以配置多個工作人員的外部系統負載。此外,這可以使您能夠使用一致性散列來避免某些消息的並行處理。

至於工作人員 - 在一個項目中,我使用了第一種方式,但對工作人員使用固定調度程序 - 因此他們總是使用相同的線程來處理消息,而不會影響其他系統部件。如果你有一個相當恆定的負載,這很好。

+0

感謝您的回覆,這聽起來像我們正在接近這個以相當類似的方式對自己這是很好的......稍後將發佈一個答案,一旦我們制定了什麼適合我們。 – lachy

2

其實第二個選項(ReceiveAsync)對於您的問題是完全有效的解決方案。唯一的風險是,在這種情況下,你會放慢發送者,因爲actor現在將異步等待HTTP請求完成。這意味着,如果高比例的信息會不斷推動,那麼演員本身可能會不知所措。

如果是這樣的話,你可以:

  1. 增加消費者(在HTTP連接的另一端聽衆)的數量,以跟上步伐。
  2. 使用阿卡流代替演員來模擬您的問題。流內置支持背壓,可以在上游應用,直到它到達請求跟蹤的原始源。
+0

感謝您的回覆。我們將嘗試使用池路由器的ReceiveAsync並進行一些負載測試,以瞭解它是如何發生的。如果這對我們不好,可能會看看Akka Streams。 – lachy