2016-09-22 16 views
0

我注意到,當我的數據庫發生故障時,對我的Django應用程序的查詢提供了超時而不是立即將500返回給客戶端。Django AdminEmailHandler在數據庫不可訪問時掛起

跟蹤問題我在配置中將數據庫connect_timeout設置爲5秒(explained here),並且日誌在日誌中顯示得比較快,但是在打印異常之後,客戶端在30秒之後纔會收到結果。

OperationalError: (2003, "Can't connect to MySQL server on 'db.example.com' (4)") 

調試的是與PDB發生的事情,我發現這個問題是在django.utils.log AdminEmailHandler,當它試圖產生異常的郵件。

要生成調用django.views.debug ExceptionReporter.get_traceback_text()看起來對追溯和所有幀的郵件然後爲每個幀上的所有變量,而這些變量之一是查詢集那觸發了例外。

生成錯誤電子郵件會多次訪問查詢集,這些查詢集生成數據庫連接超時,生成更多數據庫超時,因此對客戶端的錯誤響應時間非常長。

什麼是避免此問題的最佳方法?

回答

0

雖然沒有更好的選擇,但這是我實施的解決方案。

我已經設置了一個自定義的AdminEmailHandler來檢查的異常,並在數據庫的情況下OperationalError跳過異常,發送和錯誤,而不是。

import logging 

from django.utils.log import AdminEmailHandler 
from django.db.utils import OperationalError 

logger = logging.getLogger('mylogger') 

class CustomAdminEmailHandler(AdminEmailHandler): 

     # When mail is because of exception conencting to DB, avoid rendering the email, 
     # rendering email makes connections to DB making the query hang in multiple DB 
     # connection timeouts. 
     if record.exc_info: 
      exc_type, exc_value, exc_traceback = record.exc_info 
      if exc_type == OperationalError: 
       logger.error(exc_value, exc_info=False) 
       return 

     super(CustomAdminEmailHandler, self).emit(record) 

而且在settings.py

LOGGING = { 
    'version': 1, 
    'disable_existing_loggers': False, 
    'formatters': { 
     'simple': { 
      'format': '%(asctime)s %(levelname)s %(module)s:%(funcName)s() %(message)s' 
     }, 
    }, 
    'handlers': { 
     'send_mail': { 
      'level': 'ERROR', 
      'class': 'myapp.handlers.CustomdAdminEmailHandler', 
      'include_html': False, 
     }, 
    }, 
    'loggers': { 
     'django': { 
      'handlers': ['send_mail'], 
      'level': 'INFO' 
     }, 
     'mylogger': { 
      'handlers': ['send_mail'], 
      'level': 'INFO' 
     }, 
    } 
} 

我還建立數據庫連接超時1秒,我不想請求,該數據庫不能訪問的情況下排隊,這當連接返回可能導致服務器關閉時,可能會導致非常高的負載。