Celeryタスク内でScrapy解析機能(10分ほどかかることもあります)を使用しているときに、これが発生します。
私が使用します:-Django == 1.6.5-Django-celery == 3.1.16-celery == 3.1.16-psycopg2 == 2.5.5(psycopg2 == 2.5.4も使用しました)
[2015-07-19 11:27:49,488:CRITICAL/MainProcess]タスクmyapp.parse_items [63fc40eb-c0d6-46f4-a64e-acce8301d29a]内部エラー:InterfaceError( 'connection already closed'、) トレースバック(最新の呼び出しは最後): ファイル "/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/celery/app/trace.py "、284行目、trace_task uuid、retval、SUCCESS、request = task_request、 ファイル" /home/mo/Work/python/pb-env/local/lib/python2.7/ site-packages/celery/backends/base.py "、行248、store_result request = request、** kwargs) ファイル"/home/mo/Work/python/pb-env /local/lib/python2.7/site-packages/djcelery/backends/database.py"、29行目の_store_result traceback = traceback、children = self.current_task_children(request)、 ファイル「/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/djcelery/managers.py」の42行目の_inner に、fun(* args、 ** kwargs) ファイル "/home/mo/Work/python/pb-env/local/lib/python2.7/ site-packages/djcelery/managers.py "、行181、store_result 内の 'meta':{'children':children}}) ファイル"/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/djcelery/managers.py "、87行目のupdate_or_create でget get_queryset(self).update_or_create(** kwargs) を返しますファイル "/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/djcelery/managers.py"、70行目、update_or_create obj、created = self。 get_or_create(** kwargs) ファイル "/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/Django/db/models/query.py"、line 376、get_or_create でself.get(** lookup)を返す、False ファイル "/home/mo/Work/python/pb-env/local/lib/python2.7/site- packages/Django/db/models/query.py "、304行目、get num = len(clone) ファイル"/home/mo/Work/python/pb-env/local /lib/python2.7/site-packages/Django/db/models/query.py"、77行、__ len __ self._fetch_all() ファイル "/ home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/Django/db/models/query.py "、857行目、_fetch_all 内。self._result_cache= list(self.iterator()) ファイル「/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/Django/db/models/query.py」、行220、イテレータ compiler.results_iter(): ファイルの行の場合 "/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/Django/db/models/sql /compiler.py "、行713、self.execute_sql(MULTI)の行のresults_iter 内: ファイル"/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/Django/db/models/sql/compiler.py "、行785、execute_sql カーソル= self.connection.cursor() ファイル"/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/Django/db/backends/__ init__.py "、line 160、in cursor cursor = self.make_debug_cursor(self ._cursor()) ファイル "/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/Django/db/backends/__init__.py"、134行、 _cursor return self.create_cursor() ファイル "/home/mo/Work/python/pb-env/local/lib/python2.7/site-packages/Django/db/utils。 __exit __ のpy "、99行目。six.reraise(dj_exc_type、dj_exc_value、traceback) ファイル" /home/mo/Work/python/pb-env/local/lib/python2.7 /site-packages/Django/db/backends/__init__.py"、134行目、_cursor でself.create_cursor() ファイル "/ home/mo/Work/python/pb- env/local/lib/python2.7/site-packages/Django/db/backends/postgresql_psycopg2/base.py "、行137、create_cursor カーソル= self.connection.cursor() InterfaceError:接続はすでに閉じられています
残念ながら、これはDjango + psycopg2 +セロリコンボの問題です。これは、古い未解決の問題です。
このスレッドを見て理解してください: https://github.com/celery/Django-celery/issues/121
基本的に、セロリはワーカーを開始すると、Django.dbフレームワークからデータベース接続をフォークします。何らかの理由でこの接続が切断された場合、新しい接続は作成されません。 Django.dbライブラリを使用してデータベース接続が切断されたことを検出する方法がない場合、Celeryはこの問題とは何の関係もありません。 Djangoは、接続を開始するだけでwsgi呼び出しを受信するため(接続プールなし)、いつ発生しても通知しません。大量の実稼働環境で同じ問題が発生しましたマシンワーカー、場合によっては、これらのマシンはpostgresサーバーとの接続を失いました。
セロリの各マスタープロセスをLinuxのスーパーバイザハンドラとウォッチャに配置し、psycopg2.InterfaceErrorを処理するデコレータを実装して解決しました。この関数が発生すると、システムコールがディスパッチされ、スーパーバイザがSIGINTで正常に再起動します。
編集:
より良い解決策を見つけました。私はこのようにセロリタスクのベースクラスを実装しました:
from Django.db import connection
import celery
class FaultTolerantTask(celery.Task):
""" Implements after return hook to close the invalid connection.
This way, Django is forced to serve a new connection for the next
task.
"""
abstract = True
def after_return(self, *args, **kwargs):
connection.close()
@celery.task(base=FaultTolerantTask)
def my_task():
# my database dependent code here
私はそれもあなたの問題を解決すると信じています。
みんなと emanuelcds 、
私も同じ問題を抱えていましたが、コードを更新してセロリ用の新しいローダーを作成しました:
from djcelery.loaders import DjangoLoader
from Django import db
class CustomDjangoLoader(DjangoLoader):
def on_task_init(self, task_id, task):
"""Called before every task."""
for conn in db.connections.all():
conn.close_if_unusable_or_obsolete()
super(CustomDjangoLoader, self).on_task_init(task_id, task)
もちろん、djceleryを使用している場合は、設定で次のようなものが必要になります。
CELERY_LOADER = 'myproject.loaders.CustomDjangoLoader'
os.environ['CELERY_LOADER'] = CELERY_LOADER
私はまだそれをテストする必要があります、私は更新します。