8

Django アプリケーションを実行しています。以前は Apache + mod_python の下にありましたが、すべて問題ありませんでした。Lighttpd + FastCGI に切り替えました。今、私はランダムに次の例外を受け取ります(それが現れる場所も時間も予測できないようです)。ランダムで、FastCGI に切り替えた後にのみ表示されるため、何らかの設定が関係していると思われます。

グーグルで検索するといくつかの結果が見つかりましたが、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.
4

13 に答える 13

5

考えられる解決策: http://groups.google.com/group/django-users/browse_thread/thread/2c7421cdb9b99e48

最近まで、これを Django 1.1.1 でテストしたいと思っていました。この例外は再びスローされますか...驚き、再び発生しました。これをデバッグするのに少し時間がかかりましたが、役立つヒントは、(前)フォーク時にのみ表示されることでした。したがって、これらの例外がランダムに発生する人のために、私は言うことができます...コードを修正してください:)わかりました..真剣に、これを行う方法は常にほとんどないので、最初にどこに問題があるかを説明させてください。データベースから構成を読み取るなど、モジュールのいずれかがインポートされるときにデータベースにアクセスすると、このエラーが発生します。fastcgi-prefork アプリケーションが開始されると、最初にすべてのモジュールがインポートされ、これが子をフォークした後でのみインポートされます。インポート中にデータベース接続を確立した場合、すべての子プロセスはそのオブジェクトの正確なコピーを持ちます。この接続は、要求フェーズ (request_finished シグナル) の終わりに閉じられています。したがって、リクエストを処理するために呼び出される最初の子は、この接続を閉じます。しかし、残りの子プロセスはどうなるでしょうか? 彼らは、データベースへの接続が開いていて、おそらく機能していると信じているため、データベース操作を行うと例外が発生します。これがスレッド実行モデルに表示されないのはなぜですか? スレッドが同じオブジェクトを使用しており、他のスレッドがいつ接続を閉じているかを知っているためだと思います。これを修正する方法は?最善の方法はコードを修正することですが、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。したがって、リクエストを処理するために呼び出される最初の子は、この接続を閉じます。しかし、残りの子プロセスはどうなるでしょうか? 彼らは、データベースへの接続が開いていて、おそらく機能していると信じているため、データベース操作を行うと例外が発生します。これがスレッド実行モデルに表示されないのはなぜですか? スレッドが同じオブジェクトを使用しており、他のスレッドがいつ接続を閉じているかを知っているためだと思います。これを修正する方法は?最善の方法はコードを修正することですが、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。したがって、リクエストを処理するために呼び出される最初の子は、この接続を閉じます。しかし、残りの子プロセスはどうなるでしょうか? 彼らは、データベースへの接続が開いていて、おそらく機能していると信じているため、データベース操作を行うと例外が発生します。これがスレッド実行モデルに表示されないのはなぜですか? スレッドが同じオブジェクトを使用しており、他のスレッドがいつ接続を閉じているかを知っているためだと思います。これを修正する方法は?最善の方法はコードを修正することですが、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。しかし、残りの子プロセスはどうなるでしょうか? 彼らは、データベースへの接続が開いていて、おそらく機能していると信じているため、データベース操作を行うと例外が発生します。これがスレッド実行モデルに表示されないのはなぜですか? スレッドが同じオブジェクトを使用しており、他のスレッドがいつ接続を閉じているかを知っているためだと思います。これを修正する方法は?最善の方法はコードを修正することですが、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。しかし、残りの子プロセスはどうなるでしょうか? 彼らは、データベースへの接続が開いていて、おそらく機能していると信じているため、データベース操作を行うと例外が発生します。これがスレッド実行モデルに表示されないのはなぜですか? スレッドが同じオブジェクトを使用しており、他のスレッドがいつ接続を閉じているかを知っているためだと思います。これを修正する方法は?最善の方法はコードを修正することですが、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。しかし、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。しかし、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。

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

理想的な考えではありません.DBに2回接続することは、せいぜい回避策です。


考えられる解決策: 接続プーリング (pgpool、pgbouncer) を使用して、DB 接続をプールして安定させ、FCGI デーモンにすばやく渡します。

問題は、これが別のバグを引き起こし、psycopg2 が2 回切断しようとしているため、 InterfaceErrorを発生させることです (pgbouncer は既にこれを処理しています)。

現在、原因は Django シグナルrequest_finishedがconnection.close()をトリガーし、既に切断されていても大声で失敗することです。リクエストがすでに終了しているかのように、DB 接続はもう気にしないので、この動作は望ましくないと思います。これを修正するためのパッチは簡単なはずです。

関連するトレースバック:

 /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/__init__.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/__init__.py

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

それ以外は、アイデアが不足しています。

于 2010-03-23T21:57:07.560 に答える
0

糸脱毛の問題のようなにおいがします。Djangoはスレッドセーフであるとは保証されていませんが、ファイル内のドキュメントにはDjango/FCGIをそのように実行できることが示されているようです。preforkで実行してみて、サーバーのがらくたを打ち負かしてください。問題が解決した場合...

于 2008-12-26T17:29:32.383 に答える
0

セッションをキャッシュに保存しないのはなぜですか? 設定

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

また、 pgbouncerで postgres を使用することもできます(postgres - prefork サーバーであり、一度に多くの接続/切断を行うのは好ましくありません) が、最初に postgresql.log を確認してください。

別のバージョン - セッション テーブルに多くのレコードがあり、django-admin.py のクリーンアップが役立ちます。

于 2009-11-07T00:07:35.073 に答える
0

私は最近同じ問題を経験しました(lighttpd、fastcgi、postgre)。何日も成功せずに解決策を探し、最後の手段として mysql に切り替えました。問題はなくなりました。

于 2009-06-27T19:17:03.837 に答える
0

method=prefork から method=threaded に変更すると、問題が解決しました。

于 2010-03-05T23:06:49.823 に答える
0

関数の 1 つにデフォルトの ORM を使用していない geodjango モデルを使用する場合の同様の問題を修正しました。接続を手動で閉じる行を追加すると、エラーはなくなりました。

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

ただし、ユーザーのログイン/セッションで何かを行うと、エラーがランダムに表示されます (リクエストの約 50%)。

于 2009-03-13T23:56:27.060 に答える
0

フレームワークとしてdjangoではなくピラミッドを使用している場合でも、これに答えようとします。私は長い間この問題に直面していました。問題は、テストでこのエラーを生成するのが本当に難しいということでした...とにかく。最後に、セッション、スコープ付きセッション、セッションのインスタンス、エンジン、接続などのすべてを掘り下げて解決しました。これを見つけました:

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

このアプローチでは、リスナーをエンジンの接続プールに追加するだけです。リスナーでは、静的選択がデータベースに照会されます。失敗した場合、プールは完全に失敗する前にデータベースへの新しい接続を確立しようとします。重要: これは、他のものがデータベースにスローされる前に発生します。したがって、コードの残りの部分が失敗するのを防ぐために、接続を事前にチェックすることができます。

これはエラー自体を解決しないため、きれいな解決策ではありませんが、魅力のように機能します。これが誰かに役立つことを願っています。

于 2015-10-14T14:57:08.777 に答える
0

最後に、Apache + mod_python に戻しました (これ以外にも fcgi でランダムなエラーが発生していました)。現在はすべてが良好で安定しています。

質問はまだ未解決のままです。誰かが将来この問題を抱えて解決した場合に備えて、後で参照できるようにここに解決策を記録できます。:)

于 2009-03-02T11:23:49.783 に答える
0

スイッチでは、PostgreSQL クライアント/サーバーのバージョンを変更しましたか?

私は php+mysql で同様の問題を見たことがありますが、原因はクライアント/サーバー バージョン間の非互換性でした (同じメジャー バージョンを持っていたとしても!)

于 2008-12-26T09:43:27.020 に答える
0

おそらく、PYTHONPATH と PATH 環境変数は両方のセットアップ (Apache+mod_python と lighttpd + FastCGI) で異なります。

于 2009-02-13T17:29:29.383 に答える
0

問題は主にインポートにある可能性があります。少なくともそれが私に起こったことです。Webから何も見つけられなかった後、私は自分のソリューションを書きました。ここで私のブログ投稿を確認してください: Simple Python Utility to check all Imports in your projects

もちろん、これは元の問題の解決策にすぐに到達するのに役立つだけであり、問​​題自体の実際の解決策にはなりません.

于 2009-11-16T18:46:07.967 に答える
-1

Python 2.5.x(具体的には2.5.4)へのダウングレードを検討しましたか?後方互換性のない変更がいくつかあるため、Python2.6ではDjangoが成熟しているとは見なされないと思います。しかし、これで問題が解決するとは思えません。

また、Django 1.0.2はいくつかの悪質な小さなバグを修正したので、それを実行していることを確認してください。これで問題が解決する可能性があります。

于 2009-04-29T18:35:06.703 に答える