簡體   English   中英

使用 eventlet 解決 celery 任務中的線程數據庫問題

[英]Threading database issues in celery tasks using eventlet

我在開發虛擬機“ubuntu/trusty”下有一個項目。 我將virtualenv與以下軟件包一起使用:

celery 3.1.23
eventlet 0.18.4
django 1.8.15
mysqlclient 1.3.9

Python 版本為 3.4.3。 MySql 版本為 5.5。

我使用帶有eventlet主管作為工作人員來運行一些服務和其中的celery任務。 這是主管配置的一部分:

[program:celery-worker-default]
command=/home/vagrant/.virtualenvs/meridian/bin/python /vagrant/meridian/meridian/manage.py celery worker --loglevel=INFO -P eventlet -c 3 -Q default -E -n default.queue
directory=/vagrant/meridian/meridian
user=vagrant
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/celery-worker-default-stdout.log
stderr_logfile=/var/log/supervisor/celery-worker-default-stderr.log
priority=999
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=5

當任務運行時,它們失敗並顯示以下堆棧跟蹤:

Traceback (most recent call last):
  File "/home/vagrant/.virtualenvs/meridian/lib/python3.4/site-packages/celery/app/trace.py", line 231, in trace_task
    loader_task_init(uuid, task)
  File "/home/vagrant/.virtualenvs/meridian/lib/python3.4/site-packages/djcelery/loaders.py", line 114, in on_task_init
    self.close_database()
  File "/home/vagrant/.virtualenvs/meridian/lib/python3.4/site-packages/djcelery/loaders.py", line 85, in close_database
    return self._close_database()
  File "/home/vagrant/.virtualenvs/meridian/lib/python3.4/site-packages/djcelery/loaders.py", line 76, in _close_database
    close()
  File "/home/vagrant/.virtualenvs/meridian/lib/python3.4/site-packages/django/db/__init__.py", line 64, in close_old_connections
    conn.close_if_unusable_or_obsolete()
  File "/home/vagrant/.virtualenvs/meridian/lib/python3.4/site-packages/django/db/backends/base/base.py", line 403, in close_if_unusable_or_obsolete
    self.close()
  File "/home/vagrant/.virtualenvs/meridian/lib/python3.4/site-packages/django/db/backends/base/base.py", line 191, in close
    self.validate_thread_sharing()
  File "/home/vagrant/.virtualenvs/meridian/lib/python3.4/site-packages/django/db/backends/base/base.py", line 421, in validate_thread_sharing
    % (self.alias, self._thread_ident, thread.get_ident()))
django.db.utils.DatabaseError: DatabaseWrapper objects created in a thread can only be used in that same thread. The object with alias 'default' was created in thread id 140089123953704 and this is thread id 140088751748512.

任何包含數據庫操作的任務都會失敗。

我嘗試在任務主體中使用select_for_update()with atomic() :,但沒有成功。

我也在網上搜索了有關該問題的信息,但沒有找到解決方案。

有人知道如何解決這個問題嗎?

為Celery找到類似on_load鈎子的東西,並在下面輸入以下代碼:

import eventlet
eventlet.monkey_patch(MySQLdb=True)

它必須在任何Django代碼之前執行。

我找到了答案。 問題是我曾經在manage.py管理腳本下運行芹菜:

[program:celery-worker-default]
command=/home/vagrant/.virtualenvs/meridian/bin/python /vagrant/meridian/meridian/manage.py celery worker --loglevel=INFO -P eventlet -c 3 -Q default -E -n default.queue

我用這種方式重寫了這一行:

[program:celery-worker-default]
command=bash -c "/vagrant/meridian/meridian/start_default_queue.sh"

這是start_default_queue.sh的內容:

source /usr/share/virtualenvwrapper/virtualenvwrapper.sh
source /home/vagrant/.virtualenvs/meridian/bin/activate
workon meridian
exec celery worker --loglevel=INFO -P eventlet -c 3 -Q default -E -n default.queue

我不知道為什么,但直接運行芹菜工人已經解決了這個神秘的問題。

我剛剛遇到了同樣的問題,並且能夠通過添加來解決它

numprocs = 1

到我的 celery 服務的監督配置。 在您的示例中,這可能如下所示:

[program:celery-worker-default]
command=/home/vagrant/.virtualenvs/meridian/bin/python /vagrant/meridian/meridian/manage.py celery worker --loglevel=INFO -P eventlet -c 3 -Q default -E -n default.queue
directory=/vagrant/meridian/meridian
numprocs = 1
…

我不太清楚為什么這會改變任何東西,因為值 1 也應該是默認值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM