簡體   English   中英

將RabbitMQ的流數據並行加載到Postgres

[英]Loading Streaming Data from RabbitMQ to Postgres in Parallel

我對Node.js還是有些陌生,所以我對並行處理並行I / O操作的方式並不熟悉。

我正在計划一個Node.js應用程序以將流數據從RabbitMQ加載到Postgres。 這些負載將在系統運行期間發生,因此不是大負載。

我希望開始時的吞吐量要求相當低(也許每分鍾50-100條記錄)。 但是我想對應用程序進行規划,以便可以根據需求擴展到更大的容量。

我正在嘗試思考並行性如何工作。 我對流的第一印象以及如何引入並行性是:

  1. 從隊列中讀取消息
  2. 開始將數據加載到Postgres的查詢,這將回調推送到Node堆棧
  3. 事件循環可以自由地從隊列中讀取另一條消息(如果有),這將啟動另一個查詢
  4. 重復

相信以這種方式啟動的查詢將與PG連接池中的連接數並行運行。 這是一個很好的假設嗎?

通過這種簡單的流程,並行查詢的限制似乎就是Postgres連接池的大小。 我可以將其設置為與吞吐量所需的大小一樣大(並且服務器和后端數據庫可以處理),這將成為我可以並行處理多少條消息的限制因素。 聽起來對嗎?

對於實例化多少個並行I / O節點,我還沒有找到很好的參考。 Node最終會因為我的事件循環生成太多尚未解決的I / O請求而阻塞(如果沒有,我假設pg在必須等待連接時會將查詢放在回調堆棧上)? 啟動Node時是否可以通過設置開關來影響這些限制? 我是否正確假設libuv和“ pg” lib實際上將在一個Node.js進程中並行運行這些查詢? 如果這些假設是正確的,我會認為在達到libuv並行性限制之前(或者如果同時將連接池的大小調整為服務器上的內核數),我會達到連接池大小的限制。

另外,與上面有關節點啟動並行I / O請求的討論有關,如何防止Node盡快將消息從隊列中拉出並排隊I / O請求? 我認為這可能會導致內存消耗問題。 這與我有關啟動參數的問題有關,以限制創建的並行I / O請求的數量。 在這一點上,我還不太了解,所以也許不必擔心(默認情況下,Node不會創建比內核更多的並行I / O請求,從而提供自然的限制?)。

我想知道的另一件事是何時/如何並行運行該程序的多個副本會有所幫助? 因為Postgres連接池似乎是此處並行化的驅動程序,所以甚至在一台主機上也沒有關系嗎? 如果是這種情況,我可能每個主機只運行一個副本,而僅在其他主機上運行其他副本以分散負載。

如您所見,在嘗試這條路之前,我正在嘗試獲得一些基本假設。 洞察力和指向良好參考文檔的指針將不勝感激。

我通過測試編寫的原型解決了這一問題。 一些觀察:

  1. 如果我沒有在RabbitMQ通道上設置預取,Node將在幾秒鍾內將所有消息從隊列中拉出。 我進行了一個測試,隊列中有10萬條消息,而Node在幾秒鍾內將所有10萬條消息都刪除了,盡管實際處理這些消息需要花費幾分鍾。
  2. 上面#1中提到的行為是不可取的,因為Node必須將所有消息緩存在內存中。 在我的測試中,當快速拉出所有這些消息時,Node占用了2GB,而如果我設置預取以匹配數據庫連接的數量,則Node僅占用80 MB並緩慢耗盡了隊列,因為它完成了對消息和消息的處理。發送回ACK。
  3. 運行該程序的單個Node實例使我的CPU利用率達到100%。

因此,故事的寓意似乎是:

  1. 節點可以產生任意數量的異步I / O處理程序(受可用內存限制)
  2. 在這種情況下,您希望限制節點產生的異步I / O請求數量,以避免過多的內存使用。
  3. 為此工作負載創建其他子進程沒有什么區別。 並行度的單位是數據庫連接池的大小。 如果我的工作量在JavaScript中做得更多,而不僅僅是委派給Postgres,則其他子進程將有所幫助。 但是在這種情況下,所有的I / O(並且幸運的是I / O不需要Node線程池),因此其他子進程什么也不做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM