如何在不升級伺服器的情況下防止管理插件中陳舊/錯誤的 RabbitMQ 連接物件的擴散?

如何在不升級伺服器的情況下防止管理插件中陳舊/錯誤的 RabbitMQ 連接物件的擴散?

情境:

我們使用 RabbitMQ 2.8.4 HA 叢集在中型(數百到數千台伺服器)資料中心進行訊息傳遞。訊息傳遞功能對於我們的應用程式至關重要。

我們使用 C 用戶端 API 進行 AMQP/RabbitMQ 操作,並使用 RabbitMQ 管理插件的 HTTP API 定期監控佇列狀態並根據大小/吞吐量等發送警報。

允許從客戶端到訊息傳遞伺服器的唯一連接埠/連線位於 AMQP 連接埠和用於管理 API 的 HTTP 上。

在不久的將來,管理層決定訊息叢集的停機(這意味著應用程式的某些請求部分的停機)是不可接受的。幾個月後就可以實現,但在此之前,銷售驅動的擔憂將不允許我們維護訊息系統。這很糟糕,但我們(基礎設施/devops 人員)無法撥打這些電話。

問題:

一段時間以來,我們一直受到《中》中討論的問題的傷害。這個問題。在連接風暴之後,或新客戶端在很長一段時間內非常頻繁地連接和使用 AMQP 系統後,RabbitMQ 管理 API 會顯示數十萬個被列為「正在運行」的連接,這些連接不再存在。netstatlsof以及其他診斷證明與這些連接對應的套接字未在客戶端上開啟;由於某種原因,管理 API 無法修剪條目。rabbitmqctl list_connections有時會顯示一些不存在的連接仍然打開,但它總是顯示比管理 API 少得多,並且它的“過時”檢測似乎比 API 更好,並且它最終從其列表中清除了錯誤連接。

當我們嘗試透過 Web UI 刪除這些「錯誤」連線之一時,頁面不會回應我們按下的「刪除」鍵,並且該連線仍保留在清單中。當我們嘗試透過在 JSON API 中傳送 DELETE 來刪除它時,我們收到 500 伺服器錯誤,指示連接無效,因此無法刪除它(正如上面連結的 SO 問題中所述)。

經過長時間累積這些不存在的連結物件後,會發生三件壞事(排名不分先後):

  • RabbitMQ 伺服器有大量記憶體峰值(不知從何而來;它們與管理 API 中的緩慢連接蠕變並不對應,儘管其記憶體消耗確實隨著時間的推移而緩慢增長)。這通常會導致崩潰。
  • 管理 API 停止回應請求(API 客戶端逾時)。
  • RabbitMQ 伺服器本身偶爾會拒絕來自未使用 HTTP/管理 API 執行任何操作的 AMQP 用戶端的連線。

如果這個問題開始破壞我們的應用程序,我們必須執行以下兩件事之一: * 重新啟動整個訊息集群,這很糟糕,因為它會導致短暫的停機,而且很糟糕,因為在此過程中訊息可能會被刪除。 * 重新啟動並清除管理 API 的資料庫,這很糟糕,因為我們無法使用管理 API,更糟的是,它經常會破壞管理 API,導致它無法再次正常啟動,直到我們重新啟動整個集群,如下所示第一顆子彈。

大多數遇到類似問題的人都透過升級到 RabbitMQ 3.* 來解決這些問題。我們既沒有時間、許可,也沒有停機時間授權來進行這樣的專案。即使由於這個問題,我們重新啟動叢集時遇到週期性的長達幾分鐘的中斷,我們也無權升級。這純粹是政治限制,但卻是不幸的現實。

問題:

鑑於我們在不久的將來無法升級 RabbitMQ,並且需要繼續使用管理 API,我們如何解決導致訊息叢集故障的持久、過時連接的問題?

我們有能力開發新的/不同的客戶端程式碼,並在訊息傳遞伺服器本身上運行作業,但我們沒有能力rabbitmqctl在本地或透過ssh任何客戶端電腦使用。

我們嘗試過的:

  • 我們嘗試切換 AMQP 客戶端庫,希望更好的客戶端能夠自行清理並且不會留下過時的連接,但沒有成功。問題依然存在。
  • 我們嘗試過使用RabbitMQ 伺服器本身的tcp_keepalive和TCP 設定。exit_on_close這些值的組合無法解決該問題。
  • 我們製作了一個腳本,它會迭代從 JSON API 連接列表返回的所有連接,並為每個打開時間比使用時所需時間長的連接發送 DELETE。所有此類請求都會遇到 500 伺服器錯誤,如上面連結的 SO 問題中所述。

答案1

你不斷地定期重新啟動一切。

另一種選擇是將修復程序從 3.x 向後移植到當前版本,但如果不允許升級,您可能也不會被允許執行此操作。而且幾乎可以肯定,這比升級要多得多的工作,特別是如果 RabbitMQ 程式碼已被大幅重構的話。

直到你可以改變政治根據情況,這些是您的選擇。

相關內容