![](/img/trans.png)
[英]ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds)
[英]Sidekiq returns “ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds)” on AWS RDS
我正在使用Sidekiq在AWS服務器上創建PDF文檔,以在后台處理此作業。
在創建PDF文件的過程中,[Rails]應用程序正在池化數據庫以檢查是否已創建PDF文件(間隔:2秒)。
今天早上,我在Sidekiq端收到此錯誤消息:
ActiveRecord::ConnectionTimeoutError: could not obtain a database connection within 5.000 seconds (waited 5.000 seconds)
我正在將Amazon RDS與MySQL一起使用。
作為一個臨時解決方案,我將database.yml
的pool
參數從10
增加到了30
,但是我意識到這只是一個臨時補丁。
如何正確修復?
謝謝
我認為您的解決方案實際上是正確的。 ActiveRecord::ConnectionPool
是基於線程的,即它嘗試為每個要與數據庫一起使用的線程獲取單獨的連接。 如果有更多線程想要訪問數據庫,則連接池的總大小(使用database.yml
的pool
選項配置),如果釋放了來自其他線程的連接,則ConnectionPool
嘗試默認最多等待5秒。 在這5秒鍾的超時后,將引發ActiveRecord::ConnectionTimeoutError
異常。
現在, Sidekiq 默認使用25個工作線程 。 因此,在更高的負載下,完全有可能有多達25個作業(線程)嘗試同時訪問數據庫。 如果將pool
設置為10,則多余的工作人員必須等待其他工人完成,並且可能某些線程不得不等待太長時間。
因此,要么像您那樣將連接池的大小至少增大到至少稍大於25(sidekiq工作程序的數量), 要么通過像sidekiq -c 5
那樣運行它以減少工作程序來運行sidekiq -c 5
。 最后,始終確保您在MySQL端允許足夠的傳入連接(默認情況下,它超過100個)。
輪詢通常不能擴展為解決方案。
在不了解您的應用程序結構的更多信息的情況下,我很想利用來自諸如gem -ruby之類的gem的並發構造。
具體而言,PDF文件的創建與“ 未來”或“ 承諾”的概念非常接近
我會考慮重新組織您的工人:
您的PDF生成代碼應為Promise。 它應該只打開數據庫連接足夠長的時間,以將生成的PDF寫入數據庫。 而不是同時進行pdf生成。
您的主要應用程序代碼應照常在Sidekiq上增加PDF生成承諾。 而不是輪詢數據庫; 此代碼只是等待Promise完成或失敗; 如果Promise成功完成,則PDF位於數據庫中;如果Promise失敗,則具有異常跟蹤等。
與往常一樣,ymmv
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.