Django的FastCGI的+ - 随机提高OperationalError
题
我运行Django应用程序。有它在Apache + mod_python的面前,它是一切OK。切换到Lighttpd的FastCGI的+。现在我随机得到以下异常(无论是地方还是它看起来似乎是可预见的时间)。由于它是随机的,它只是切换到FastCGI的后出现,我认为它是与一些设置。
googleing当发现了几个结果,但是它们似乎与设置maxrequests = 1。然而,我使用的默认值,即0。
任何想法去哪里寻找?
PS。我使用PostgreSQL。可能与该为好,因为使数据库查询时出现的异常。
File "/usr/lib/python2.6/site-packages/django/core/handlers/base.py", line 86, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.6/site-packages/django/contrib/admin/sites.py", line 140, in root
if not self.has_permission(request):
File "/usr/lib/python2.6/site-packages/django/contrib/admin/sites.py", line 99, in has_permission
return request.user.is_authenticated() and request.user.is_staff
File "/usr/lib/python2.6/site-packages/django/contrib/auth/middleware.py", line 5, in __get__
request._cached_user = get_user(request)
File "/usr/lib/python2.6/site-packages/django/contrib/auth/__init__.py", line 83, in get_user
user_id = request.session[SESSION_KEY]
File "/usr/lib/python2.6/site-packages/django/contrib/sessions/backends/base.py", line 46, in __getitem__
return self._session[key]
File "/usr/lib/python2.6/site-packages/django/contrib/sessions/backends/base.py", line 172, in _get_session
self._session_cache = self.load()
File "/usr/lib/python2.6/site-packages/django/contrib/sessions/backends/db.py", line 16, in load
expire_date__gt=datetime.datetime.now()
File "/usr/lib/python2.6/site-packages/django/db/models/manager.py", line 93, in get
return self.get_query_set().get(*args, **kwargs)
File "/usr/lib/python2.6/site-packages/django/db/models/query.py", line 304, in get
num = len(clone)
File "/usr/lib/python2.6/site-packages/django/db/models/query.py", line 160, in __len__
self._result_cache = list(self.iterator())
File "/usr/lib/python2.6/site-packages/django/db/models/query.py", line 275, in iterator
for row in self.query.results_iter():
File "/usr/lib/python2.6/site-packages/django/db/models/sql/query.py", line 206, in results_iter
for rows in self.execute_sql(MULTI):
File "/usr/lib/python2.6/site-packages/django/db/models/sql/query.py", line 1734, in execute_sql
cursor.execute(sql, params)
OperationalError: server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
解决方案 5
在结束我切换回的Apache + mod_python的(我是有FCGI其它随机误差,除了这一个)和一切现在是良好且稳定的。
的问题仍然保持打开状态。如果任何人有在未来这个问题并解决它,他们可以在这里记录的解决方案以供将来参考。 :)
其他提示
可能的解决方案: http://groups.google.com/组/ django的用户/ browse_thread /线程/ 2c7421cdb9b99e48
直到最近我好奇测试 这对Django的1.1.1。请问这个 抛出异常再次...惊喜, 那里又是。我花了一些 时间调试此,有用的提示是 它仅当(预)分叉显示。 因此,对于那些谁随机获得 这些例外,我可以说...修复 你的代码:)好了..严重的是,有 总是这样做的几种方法,所以 让我来解释一下冷杉哪里是 问题第一次。如果访问数据库 当您的任何模块将导入 如,例如从读取配置 数据库那么你会得到这个错误。 当你的FastCGI-prefork的应用 开始时,首先它进口的所有模块, 只有经过这个叉子的孩子。 如果你已经建立数据库连接 在进口的所有子进程 将有说的精确副本 宾语。该连接正在 在请求阶段结束时关闭 (request_finished信号)。所以第一 孩子将被调用来处理 您的要求,将关闭该 连接。但是,会发生什么事 子进程的休息吗?他们 会相信他们有开放的, 想必工作连接到 分贝,所以任何DB操作将导致 例外。这是为什么不显示 线程执行模式?我想 因为线程使用相同的对象 并且知道什么时候其他线程 关闭连接。如何解决这一问题? 最好的办法是解决你的代码...但是 这会比较困难。 其他选项,在我看来相当 干净,是在什么地方写你 应用小块代码:
from django.db import connection
from django.core import signals
def close_connection(**kwargs):
connection.close()
signals.request_started.connect(close_connection)
不理想的思想,两次连接到DB是一种变通方法的最好的。
可能的解决方法:使用连接池(pgpool,pgbouncer),所以你数据库连接池,稳定,快速递给你FCGI守护进程
问题是,这会触发另一个bug,psycopg2引发一个的 InterfaceError 的,因为它试图断开两次(pgbouncer已经处理了这个)。
现在的罪魁祸首是Django的信号的 request_finished 触发 connection.close()时,和失败响,即使它已经断开。我不认为这种行为是需要的,因为如果该请求已经完成,我们不关心数据库连接了。一种用于校正该补丁应是简单的。
相关的回溯:
/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/core/handlers/wsgi.py in __call__(self=<django.core.handlers.wsgi.WSGIHandler object at 0x24fb210>, environ={'AUTH_TYPE': 'Basic', 'DOCUMENT_ROOT': '/storage/test', 'GATEWAY_INTERFACE': 'CGI/1.1', 'HTTPS': 'off', 'HTTP_ACCEPT': 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 'HTTP_AUTHORIZATION': 'Basic dGVzdGU6c3VjZXNzbw==', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_COOKIE': '__utma=175602209.1371964931.1269354495.126938948...none); sessionid=a1990f0d8d32c78a285489586c510e8c', 'HTTP_HOST': 'www.rede-colibri.com', ...}, start_response=<function start_response at 0x24f87d0>)
246 response = self.apply_response_fixes(request, response)
247 finally:
248 signals.request_finished.send(sender=self.__class__)
249
250 try:
global signals = <module 'django.core.signals' from '/usr/local/l.../Django-1.1.1-py2.6.egg/django/core/signals.pyc'>, signals.request_finished = <django.dispatch.dispatcher.Signal object at 0x1975710>, signals.request_finished.send = <bound method Signal.send of <django.dispatch.dispatcher.Signal object at 0x1975710>>, sender undefined, self = <django.core.handlers.wsgi.WSGIHandler object at 0x24fb210>, self.__class__ = <class 'django.core.handlers.wsgi.WSGIHandler'>
/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/dispatch/dispatcher.py in send(self=<django.dispatch.dispatcher.Signal object at 0x1975710>, sender=<class 'django.core.handlers.wsgi.WSGIHandler'>, **named={})
164
165 for receiver in self._live_receivers(_make_id(sender)):
166 response = receiver(signal=self, sender=sender, **named)
167 responses.append((receiver, response))
168 return responses
response undefined, receiver = <function close_connection at 0x197b050>, signal undefined, self = <django.dispatch.dispatcher.Signal object at 0x1975710>, sender = <class 'django.core.handlers.wsgi.WSGIHandler'>, named = {}
/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/__init__.py in close_connection(**kwargs={'sender': <class 'django.core.handlers.wsgi.WSGIHandler'>, 'signal': <django.dispatch.dispatcher.Signal object at 0x1975710>})
63 # when a Django request is finished.
64 def close_connection(**kwargs):
65 connection.close()
66 signals.request_finished.connect(close_connection)
67
global connection = <django.db.backends.postgresql_psycopg2.base.DatabaseWrapper object at 0x17b14c8>, connection.close = <bound method DatabaseWrapper.close of <django.d...ycopg2.base.DatabaseWrapper object at 0x17b14c8>>
/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/backends/__init__.py in close(self=<django.db.backends.postgresql_psycopg2.base.DatabaseWrapper object at 0x17b14c8>)
74 def close(self):
75 if self.connection is not None:
76 self.connection.close()
77 self.connection = None
78
self = <django.db.backends.postgresql_psycopg2.base.DatabaseWrapper object at 0x17b14c8>, self.connection = <connection object at 0x1f80870; dsn: 'dbname=co...st=127.0.0.1 port=6432 user=postgres', closed: 2>, self.connection.close = <built-in method close of psycopg2._psycopg.connection object at 0x1f80870>
这里异常处理可以添加更宽大:
<强> /usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db / __初始化__。PY 强>
63 # when a Django request is finished.
64 def close_connection(**kwargs):
65 connection.close()
66 signals.request_finished.connect(close_connection)
或者,它可以处理在psycopg2更好,所以不抛出致命的错误,所有我们要做的是断开而且它已经是:
<强> /usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/backends / __初始化__。PY 强>
74 def close(self):
75 if self.connection is not None:
76 self.connection.close()
77 self.connection = None
除此之外,我在很短的想法。
在开关,你修改PostgreSQL客户端/服务器版本?
我已经看到了php + mysql的类似问题,而罪魁祸首是客户机/服务器版本之间的不兼容(即使它们具有相同的主要版本!)
闻起来像一个可能的线程问题。 Django是的不的保证线程安全的,虽然在文件文档似乎表明,Django的/ FCGI可以运行的方式。尝试用prefork的运行,然后打的屁滚尿流服务器。如果问题消失...
也许PYTHONPATH和环境变量PATH为两种设置(阿帕奇+ mod_python的和的lighttpd + FastCGI的)不同。
我使用未使用默认ORM对于其功能之一一个GeoDjango内置模型时固定类似的问题。当我添加了一行手动关闭错误走的连接。
http://code.djangoproject.com/ticket/9437
我仍然看到错误随机(〜请求的50%)与用户登录做的东西时/会话但是。
我通过同样的问题去最近(lighttpd的,fastcgi的&postgre)。搜索没有成功了几天的解决方案,并作为最后的手段切换到MySQL。该问题也没有了。
为什么不在缓存中存储会话? 设置
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
您也可以尝试使用的Postgres用的 pgbouncer 的(Postgres的 - prefork的服务器和不喜欢许多每次连接/断开),但首先检查你的postgresql.log
另一个版本 - 你在会话表多条记录和 django-admin.py清理的能帮
这个问题可能是主要与进口。 ATLEAST这就是发生在我身上。 我发现从网上后一无所获写我自己的解决方案。请点击这里查看我的博文:简单的Python工具来检查所有进口项目
Ofcourse这只会帮助你自行去原来的问题的解决很快,而不是你的问题的实际解决方案。
这方法变= prefork的至方法=螺纹解决了这个问题,我
我试着给一个答案,即使我'不使用Django,但金字塔的框架。我跑了这个问题,因为很长一段时间。问题是,这是真的很难产生这种错误的测试...无论如何。最后,我解决它通过会议,发动机和连接等的会话,会话作用域,实例的整个东西,我发现这个挖:
http://docs.sqlalchemy.org/烯/ rel_0_7 /型芯/ pooling.html#断开装卸悲观
此方法简单地增加一个监听到发动机的连接池。在听众的静态选择查询数据库。如果失败池尝试建立到数据库的新连接失败可言了。重要说明:此发生之前任何其他的东西被抛出到数据库。因此,可以预先检查连接是什么阻止你的代码的其余部分从失败的。
这是不是一个干净的解决方案,因为它没有解决错误本身,而是它的工作原理就像一个魅力。希望这可以帮助别人。
这是适用的报价:
"2019 anyone?"
- half of YouTube comments, circa 2019
如果有人还在用这种处理,确保你的应用程序之间的“热切分叉”,使得你的Python DB驱动程序(psycopg2
我)不共享资源。
我通过添加lazy-apps = true
选项,这将导致是叉应用进程右出了大门,而不是等待写入时复制解决上uWSGI这个问题。我想象其他WSGI / FastCGI的主机有类似的选项。
你有没有考虑降级到Python 2.5.X(2.5.4具体)?我不认为,因为有一些向后不兼容的改变Django的将被视为成熟的关于Python 2.6。不过,我怀疑这将解决您的问题。
此外,Django的1.0.2修正了一些邪恶的小错误,从而确保你运行。这非常好能解决你的问题。