你可能會被下面的django bug [1]咬傷(它還沒有固定在1。4支)
解決方法:手冊冊應用fix到你的Django源,或使用如下圖所示的WSGI模塊圍繞線程封裝(我們用這個生產系統)
from __future__ import with_statement
from django.core.handlers.wsgi import WSGIHandler as DjangoWSGIHandler
from threading import Lock
__copyright__ = "Jibe"
class WSGIHandler(DjangoWSGIHandler):
"""
This provides a threadsafe drop-in replacement of django's WSGIHandler.
Initialisation of django via a multithreaded wsgi handler is not safe.
It is vulnerable to a A-B B-A deadlock.
When two threads bootstrap django via different urls you have a change to hit
the following deadlock.
thread 1 thread 2
view A view B
import file foo import lock foo import file bar import lock bar
bootstrap django lock AppCache.write_lock
import file bar import lock bar <-- blocks
bootstrap django lock AppCache.write_lock <----- deadlock
workaround for an AB BA deadlock: wrap it in a lock C.
lock C lock C
lock A lock B
lock B lock A
release B release A
release A release A
release C release C
Thats exactly what this class does, but... only for the first few calls.
After that we remove the lock C. as the AppCache.write_lock is only held when django is booted.
If we would not remove the lock C after the first few calls, that would make the whole app single threaded again.
Usage:
in your wsgi file replace the following lines
import django.core.handlers.wsgi.WSGIHandler
application = django.core.handlers.wsgi.WSGIHandler
by
import threadsafe_wsgi
application = threadsafe_wsgi.WSGIHandler
FAQ:
Q: why would you want threading in the first place ?
A: to reduce memory. Big apps can consume hundeds of megabytes each. adding processes is then much more expensive than threads.
that memory is better spend caching, when threads are almost free.
Q: this deadlock, it looks far-fetched, is this real ?
A: yes we had this problem on production machines.
"""
__initLock = Lock() # lock C
__initialized = 0
def __call__(self, environ, start_response):
# the first calls (4) we squeeze everybody through lock C
# this basically serializes all threads
MIN_INIT_CALLS = 4
if self.__initialized < MIN_INIT_CALLS:
with self.__initLock:
ret = DjangoWSGIHandler.__call__(self, environ, start_response)
self.__initialized += 1
return ret
else:
# we are safely bootrapped, skip lock C
# now we are running multi-threaded again
return DjangoWSGIHandler.__call__(self, environ, start_response)
,並在您wsgi.py
使用下面的代碼
from threadsafe_wsgi.handlers import WSGIHandler
django_handler = WSGIHandler()
[1] https://code.djangoproject.com/ticket/18251
你在做什麼樣的監控? Munin,Monit,Nagios? – 2012-01-10 15:08:28
相關監視通過一個shell腳本完成,該腳本每30秒檢查一次服務器狀態和靜態頁面。我也有運營統計的munin(請求數量等)和nagios來監控一些其他所需的資源。 – tback 2012-01-10 15:25:10
你在settings.py中有'DEBUG = False'對嗎? – danodonovan 2012-01-10 15:34:53