[英]How to publish messages to rabbitmq with high tps, multithreading
由於通道不是線程安全的,我可以在發布之前同步通道實例,也可以在每次需要時創建一個通道並關閉它。
但在我看來,由於鎖定或創建和銷毀通道的成本,它們都沒有良好的性能。
那么我應該如何以高 tps 向rabbitmq 發布消息? 對此有何好評?
所以,第一件事。 通道不是連接。 在 RabbitMQ 中,通道與應用程序會話相同,而連接代表與服務器的底層 TCP 會話。 這個答案很好地解釋了其中的一些。
TCP 會話的創建成本很高,因此它們的生命周期往往在任何特定工作線程的生命周期之外。 創建頻道非常便宜 - 服務器所做的就是為您的頻道標識符分配一個整數,然后您就有了一個新頻道。
RabbitMQ 上的大多數操作在失敗時都會關閉通道。 這樣做是因為這樣做沒有實際后果。 他們是否會關閉底層連接,這會給應用程序帶來很多問題。
設計指南
如果您確實有很多處理正在進行,則池化適用於連接。 關於如何做到這一點的討論真的超出了我在簡短回答中所能提供的。
池化絕對不適合頻道。 通道是一種輕量級構造,旨在具有短暫的生命周期。 如果它的持續時間超過一兩次發布,那就太好了。 但是您應該預料到,每次嘗試操作時,都有可能會失敗並關閉通道。 這不會關閉底層連接,但必須重新建立新通道才能對代理執行任何操作。
消費者生命周期與渠道相關。 當通道關閉時,附加的消費者也將關閉。 設計您的消費者對象(工作線程),以便在發生這種情況時能夠獲得連接並創建新通道,然后重新訂閱自己。
避免跨線程共享通道。 一個線程=一個通道。
雖然我對 Java 客戶端沒有任何特別的經驗,但我認為鎖不是必需的,而且我當然希望實現不會做一些奇怪的事情來使 Channels 成為輕量級以外的任何東西。
如果您正在編寫自己的協議實現庫(不是必需的,但如果您需要細粒度控制也不是一個壞主意),請分配一個線程來管理每個connection
。 不要並行讀取和寫入 TCP 套接字,否則會破壞協議。
關於 Java 客戶端,我認為您可以假設通道操作(讀取和寫入等)不是線程安全的,這就是您想要堅持一個線程/一個通道范例的原因。 我認為您可以假設創建通道(連接操作)是線程安全的。
你應該使用游泳池。
例如,使用Apache 的通用對象池並提供用於打開、關閉和檢查連接的實現。 當你需要發布一條消息時,你從池中借用一個通道,使用它,然后返回它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.