Mongodb

pymongo + flask + gunicorn:“connect=False”時第一次操作前“Authentication failed”

  • March 23, 2021

我正在使用 MongoDB Atlas。我有這個 URL 用於連接:mongodb+srv://<LOGIN>:<PASSWORD>@<URL>/<DB>?retryWrites=true&w=majority&authSource=admin

我正在使用這個堆棧:flask、gunicorn、pymongo、mongoengine(我不認為它是相關的,因為 mongoengine 實際上使用 pymongo)。

獨角獸配置:

  • 同步工作者,
  • 執行緒 = 1,
  • 工人數 = 8

連接時,我正在使用,connect=False因為 pymongo 本身不是分叉安全的。connect=False它將在第一次操作之前連接到數據庫。它需要設置為False,因為 gunicorn 使用 pre-fork 模型。

但我面臨以下情況:

  1. 在第一次請求(端點進行一些數據庫操作)時,我收到此錯誤:pymongo.errors.OperationFailure: Authentication failed., full error: {'ok': 0, 'errmsg': 'Authentication failed.', 'code': 8000, 'codeName': 'AtlasError'}
  2. 在第二次請求時,一切都很好(即,數據庫操作已成功完成)。
  3. 如果你按F5多次,那麼有時你會出現“驗證失敗”的錯誤,有時一切都會好起來的。

如果我準備好connect=True了,一切都會好起來的。我從未見過此“身份驗證失敗”錯誤。

但後來我收到了這個警告資訊:UserWarning: MongoClient opened before fork. Create MongoClient only after forking. See PyMongo's documentation for details: https://pymongo.readthedocs.io/en/stable/faq.html#is-pymongo-fork-safe

所以,顯然,connect需要設置為False.

我接受了兩名工人的測試。看起來會出現這種情況:

  1. 假設我有兩個具有以下 pid 的 gunicorn 同步工作者:22429 和 22430。
  2. 我收到請求。工人 22429 處理它。一切都很好,因為它是第一個工作人員,看起來它成功地建立了數據庫連接。
  3. 我按 F5,工人 22429 再次處理它,一切都很好。
  4. 我再次按 F5,現在工人 22430 處理它。它會引發錯誤“身份驗證失敗”。
  5. 我再次按 F5,工人 22430 處理它。現在一切都很好,因為那個工人已經建立了聯繫。
  6. 現在,我所有的工人(我只有兩個)都連接到數據庫。無論我按 F5 多少次,每個請求都會成功完成。

但為什麼它發生在第一次請求上?來自 pymongo:“如果 connect=False,則在第一次操作時連接。”。如果我理解正確,pymongo 應該在實際第一次操作之前連接,成功完成連接,然後才執行該操作。

那為什麼我的第一個數據庫操作對每個工人都失敗了?我應該如何處理這個?

實際上,問題出在 Mongoengine,而不是 PyMongo。在 Mongoengine GitHub 上,我沒有找到與此問題相關的任何內容。我用 Mongoengine 嘗試了很多方法來解決這個問題,但沒有任何效果。唯一的解決方案是拒絕 Mongoengine 並僅使用 PyMongo。

我重寫了我的項目以僅使用 PyMongo。幸運的是,這只是項目的開始,所以並沒有花太多時間。重寫後,一切都按預期工作,配置完全相同。

與此問題無關:

對於那些考慮使用 Mongoengine 或 PyMongo 的人。使用 PyMongo。直接使用 PyMongo 要容易得多,因為它實現了實際的 MongoDB 文件。Mongoengine 改變了一些概念,最終很難閱讀官方 MongoDB 文件和 Mongoengine 文件,後者以不同的方式實現了 MongoDB 文件中的一些概念。是的,通過拒絕更多的抽象,您將避免像我的問題這樣的問題。

引用自:https://serverfault.com/questions/1052402