2008-12-26 30 views
8

Tôi đang chạy một ứng dụng Django. Đã có nó dưới Apache + mod_python trước, và nó đã được tất cả OK. Đã chuyển sang Lighttpd + FastCGI. Bây giờ tôi ngẫu nhiên nhận được ngoại lệ sau đây (không phải là nơi cũng như thời gian mà nó xuất hiện dường như có thể dự đoán được). Vì nó là ngẫu nhiên, và nó chỉ xuất hiện sau khi chuyển sang FastCGI, tôi cho rằng nó có liên quan đến một số cài đặt.Django + FastCGI - tăng ngẫu nhiên OperationalError

Tìm thấy một vài kết quả khi googleing, nhưng chúng dường như có liên quan đến việc đặt maxrequests = 1. Tuy nhiên, tôi sử dụng giá trị mặc định, là 0.

Bất kỳ ý tưởng nào cần tìm?

PS. Tôi đang sử dụng PostgreSQL. Cũng có thể liên quan đến điều đó, vì ngoại lệ xuất hiện khi thực hiện truy vấn cơ sở dữ liệu.

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. 

Trả lời

0

Cuối cùng, tôi chuyển trở lại Apache + mod_python (Tôi đã gặp phải các lỗi ngẫu nhiên khác với fcgi, bên cạnh cái này) và mọi thứ đều tốt và ổn định ngay bây giờ.

Câu hỏi vẫn mở. Trong trường hợp ai đó có vấn đề này trong tương lai và giải quyết nó, họ có thể ghi lại các giải pháp ở đây để tham khảo trong tương lai. :)

+2

Điều này không giải quyết được vấn đề. Chỉ cần bỏ qua nó. : P Có thể không phải là một lựa chọn cho một số người. – pkoch

0

Trong chuyển đổi, bạn có thay đổi phiên bản máy khách/máy chủ PostgreSQL không?

Tôi đã thấy vấn đề tương tự với php + mysql, và thủ phạm là sự không tương thích giữa các phiên bản client/server (mặc dù họ đã có phiên bản chính cùng!)

+0

No. Tôi chỉ chuyển Apache + mod_python thành Lighttpd + FastCGI. – ibz

0

Mùi giống như một vấn đề luồng tốt. Django là không phải là được đảm bảo an toàn chỉ mặc dù các tài liệu trong tệp dường như chỉ ra rằng Django/FCGI có thể chạy theo cách đó. Hãy thử chạy với prefork và sau đó đánh bại các crap ra khỏi máy chủ. Nếu sự cố không còn ...

+0

Tôi đang sử dụng prefork rồi. – ibz

0

Có thể biến môi trường PYTHONPATH và PATH là khác nhau cho cả hai thiết lập (Apache + mod_python và lighttpd + FastCGI).

0

Tôi đã khắc phục sự cố tương tự khi sử dụng mô hình geodjango không sử dụng ORM mặc định cho một trong các chức năng của nó. Khi tôi thêm một dòng để đóng kết nối theo cách thủ công, lỗi sẽ biến mất.

http://code.djangoproject.com/ticket/9437

tôi vẫn thấy lỗi ngẫu nhiên (~ 50% yêu cầu) khi đang làm công cụ với người sử dụng đăng nhập/phiên tuy nhiên.

-1

Bạn đã xem xét hạ cấp xuống Python 2.5.x (2.5.4 cụ thể) chưa? Tôi không nghĩ Django sẽ được coi là trưởng thành trên Python 2.6 vì có một số thay đổi không tương thích ngược. Tuy nhiên, tôi nghi ngờ điều này sẽ khắc phục được sự cố của bạn.

Ngoài ra, Django 1.0.2 đã sửa một số lỗi nhỏ bất thường để đảm bảo bạn đang chạy. Điều này rất tốt có thể khắc phục vấn đề của bạn.

0

Tôi đã trải qua cùng một vấn đề gần đây (lighttpd, fastcgi & postgre). Tìm kiếm một giải pháp cho những ngày không thành công, và như là một phương sách cuối cùng chuyển sang mysql. Vấn đề đã biến mất.

0

Tại sao không lưu trữ phiên trong bộ nhớ cache? Đặt

SESSION_ENGINE = "django.contrib.sessions.backends.cache" 

Ngoài ra bạn có thể thử sử dụng postgres với pgbouncer (postgres - prefork máy chủ và không thích nhiều kết nối/ngắt kết nối mỗi thời gian), nhưng trước hết là kiểm tra postgresql.log của bạn.

Một phiên bản khác - bạn có nhiều bản ghi trong bảng phiên và django-admin.py cleanup có thể trợ giúp.

0

Sự cố có thể chủ yếu với Nhập. Atleast thats những gì đã xảy ra với tôi. Tôi đã viết giải pháp của riêng mình sau khi không tìm thấy gì từ web. Vui lòng kiểm tra bài đăng trên blog của tôi tại đây: Simple Python Utility to check all Imports in your project

Việc này sẽ chỉ giúp bạn giải quyết vấn đề gốc một cách nhanh chóng chứ không phải giải pháp thực sự cho vấn đề của bạn.

0

Thay đổi từ phương thức = prefork thành method = threaded đã giải quyết được sự cố cho tôi.

3

giải pháp có thể: http://groups.google.com/group/django-users/browse_thread/thread/2c7421cdb9b99e48

Cho đến gần đây tôi đã tò mò muốn thử nghiệm này trên Django 1.1.1. Điều này sẽ vi phạm một lần nữa ... bất ngờ, lại ở đó. Nó đã cho tôi một số thời gian để gỡ lỗi này, gợi ý hữu ích là rằng nó chỉ hiển thị khi (trước) forking. Vì vậy, đối với những người nhận ngẫu nhiên những ngoại lệ đó, tôi có thể nói ... sửa mã của bạn :) Ok .. nghiêm túc, có luôn có vài cách để thực hiện việc này, vì vậy hãy để tôi giải thích vấn đề ở đâu trước tiên là . Nếu bạn truy cập cơ sở dữ liệu khi bất kỳ mô-đun nào của bạn sẽ nhập như, ví dụ: đọc cấu hình từ cơ sở dữ liệu sau đó bạn sẽ nhận được lỗi này. Khi ứng dụng quickcgi-prefork của bạn bắt đầu, trước tiên nó sẽ nhập tất cả các mô-đun, và chỉ sau khi dĩa này trẻ em. Nếu bạn đã thiết lập kết nối db trong quá trình nhập tất cả các quy trình trẻ em sẽ có bản sao chính xác của đối tượng đó. Kết nối này đang được đóng vào cuối yêu cầu pha (tín hiệu yêu cầu_finished). Vì vậy, đầu tiên trẻ em sẽ được gọi để xử lý yêu cầu của bạn, sẽ đóng kết nối này. Nhưng điều gì sẽ xảy ra với phần còn lại của quá trình con? Họ sẽ tin rằng họ đã mở và có lẽ là kết nối làm việc với số db, do đó, bất kỳ hoạt động nào của db cũng sẽ gây ra một ngoại lệ . Tại sao điều này không hiển thị trong mô hình thực thi luồng? Tôi giả sử vì chủ đề đang sử dụng cùng một đối tượng và biết khi nào bất kỳ chủ đề nào khác là đóng kết nối. Làm thế nào để sửa lỗi này? Cách tốt nhất là sửa mã của bạn ... nhưng điều này đôi khi có thể khó khăn. tùy chọn khác, theo ý kiến ​​của tôi khá sạch, là viết ở đâu đó trong ứng dụng của bạn đoạn mã nhỏ:

from django.db import connection 
from django.core import signals 
def close_connection(**kwargs): 
    connection.close() 
signals.request_started.connect(close_connection) 

Không suy nghĩ lý tưởng, kết nối hai lần để DB là một cách giải quyết tốt nhất.


Giải pháp có thể: sử dụng kết nối DB gộp lại và ổn định, đồng thời chuyển nhanh đến các trình nền FCGI của bạn.

Vấn đề là điều này kích hoạt một lỗi khác, psycopg2 nâng lên một giao diện Error vì nó đang cố gắng ngắt kết nối hai lần (pgbouncer đã xử lý việc này).

Bây giờ là thủ phạm là Django tín hiệu request_finished kích hoạt connection.close(), nhưng thất bại lớn ngay cả khi nó đã được ngắt kết nối. Tôi không nghĩ rằng hành vi này là mong muốn, như thể yêu cầu đã hoàn tất, chúng tôi không quan tâm đến kết nối DB nữa. Một bản vá để sửa lỗi này phải đơn giản.

Các traceback liên quan:

/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> 

xử lý ở đây có thể bổ sung thêm khoan dung Ngoại lệ:

/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2 .6.egg/django/db/__ init__.py

63 # when a Django request is finished. 
    64 def close_connection(**kwargs): 
    65  connection.close() 
    66 signals.request_finished.connect(close_connection) 

Hoặc nó có thể được xử lý tốt hơn trên psycopg2, vì vậy để không ném lỗi gây tử vong nếu tất cả chúng ta đang cố gắng làm là disconn ect và nó đã là:

/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/backends/__init__.py

74  def close(self): 
    75   if self.connection is not None: 
    76    self.connection.close() 
    77    self.connection = None 

Ngoài ra, tôi thiếu ý tưởng.

0

Tôi cố gắng đưa ra câu trả lời cho điều này ngay cả khi tôi không sử dụng django nhưng kim tự tháp làm khung. Tôi đã gặp phải vấn đề này từ lâu. Vấn đề là, thật khó để tạo ra lỗi này cho các bài kiểm tra ... Dù sao đi nữa. Cuối cùng tôi giải quyết nó bằng cách đào bới toàn bộ công cụ của phiên, phiên scoped, trường hợp của phiên, động cơ và kết nối vv Tôi thấy điều này:

http://docs.sqlalchemy.org/en/rel_0_7/core/pooling.html#disconnect-handling-pessimistic

Cách tiếp cận này chỉ đơn giản là thêm một người biết lắng nghe đến hồ bơi kết nối của động cơ. Trong trình lắng nghe, một lựa chọn tĩnh được truy vấn đến cơ sở dữ liệu. Nếu nó thất bại trong hồ bơi cố gắng thiết lập một kết nối mới vào cơ sở dữ liệu trước khi nó không thành công cả. Quan trọng: Điều này xảy ra trước khi bất kỳ nội dung nào khác được ném vào cơ sở dữ liệu. Vì vậy, nó có thể kiểm tra trước kết nối những gì ngăn chặn phần còn lại của mã của bạn từ thất bại.

Đây không phải là giải pháp sạch vì nó không tự giải quyết lỗi nhưng nó hoạt động như một sự quyến rũ. Hy vọng điều này sẽ giúp một ai đó.