簡體   English   中英

如何以高 tps、多線程向rabbitmq 發布消息

[英]How to publish messages to rabbitmq with high tps, multithreading

由於通道不是線程安全的,我可以在發布之前同步通道實例,也可以在每次需要時創建一個通道並關閉它。

但在我看來,由於鎖定或創建和銷毀通道的成本,它們都沒有良好的性能。

那么我應該如何以高 tps 向rabbitmq 發布消息? 對此有何好評?

所以,第一件事。 通道不是連接。 在 RabbitMQ 中,通道與應用程序會話相同,而連接代表與服務器的底層 TCP 會話。 這個答案很好地解釋了其中的一些。

TCP 會話的創建成本很高,因此它們的生命周期往往在任何特定工作線程的生命周期之外。 創建頻道非常便宜 - 服務器所做的就是為您的頻道標識符分配一個整數,然后您就有了一個新頻道。

RabbitMQ 上的大多數操作在失敗時都會關閉通道。 這樣做是因為這樣做沒有實際后果。 他們是否會關閉底層連接,這會給應用程序帶來很多問題。

設計指南

  1. 如果您確實有很多處理正在進行,則池化適用於連接。 關於如何做到這一點的討論真的超出了我在簡短回答中所能提供的。

  2. 池化絕對不適合頻道。 通道是一種輕量級構造,旨在具有短暫的生命周期。 如果它的持續時間超過一兩次發布,那就太好了。 但是您應該預料到,每次嘗試操作時,都有可能會失敗並關閉通道。 這不會關閉底層連接,但必須重新建立新通道才能對代理執行任何操作。

  3. 消費者生命周期與渠道相關。 當通道關閉時,附加的消費者也將關閉。 設計您的消費者對象(工作線程),以便在發生這種情況時能夠獲得連接並創建新通道,然后重新訂閱自己。

  4. 避免跨線程共享通道。 一個線程=一個通道。

  5. 雖然我對 Java 客戶端沒有任何特別的經驗,但我認為鎖不是必需的,而且我當然希望實現不會做一些奇怪的事情來使 Channels 成為輕量級以外的任何東西。

  6. 如果您正在編寫自己的協議實現庫(不是必需的,但如果您需要細粒度控制也不是一個壞主意),請分配一個線程來管理每個connection 不要並行讀取和寫入 TCP 套接字,否則會破壞協議。

  7. 關於 Java 客戶端,我認為您可以假設通道操作(讀取和寫入等)不是線程安全的,這就是您想要堅持一個線程/一個通道范例的原因。 我認為您可以假設創建通道(連接操作)是線程安全的。

你應該使用游泳池。

例如,使用Apache 的通用對象池並提供用於打開、關閉和檢查連接的實現。 當你需要發布一條消息時,你從池中借用一個通道,使用它,然后返回它。

暫無
暫無

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

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