为每个芹菜工人创建单独的数据库连接



当工人在创建后执行任务时,我一直会遇到奇怪的mysql问题。

我们使用 django 1.3,芹菜 3.1.17,djorm-ext-pool 0.5

我们从并发 3 开始芹菜过程。到目前为止,我的观察是,当工作进程启动时,它们都会获得相同的 mysql 连接。我们记录数据库连接 ID,如下所示。

from django.db import connection
connection.cursor()
logger.info("Task %s processing with db connection %s", str(task_id), str(connection.connection.thread_id()))

当所有工作线程都获得任务时,第一个成功执行,但另外两个给出奇怪的Mysql错误。它要么出现"Mysql 服务器消失"的错误,要么出现 Django 抛出"DoesNotExist"错误的情况。显然,Django 正在查询的对象确实存在。

在此错误之后,每个工作线程开始获得自己的数据库连接,之后我们没有发现任何问题。

芹菜的默认行为是什么?它是否设计为共享相同的数据库连接。如果是这样,如何处理进程间通信?理想情况下,我希望每个工作人员都有不同的数据库连接。

我尝试了以下链接中提到的代码,但不起作用。芹菜工人数据库连接池

我们还修复了下面建议的芹菜代码。https://github.com/celery/celery/issues/2453

对于那些对问题投反对票的人,请让我知道投反对票的原因。

芹菜由以下命令启动

celery -A myproject worker --loglevel=debug --concurrency=3 -Q testqueue

myproject.py作为主进程的一部分,在分叉工作进程之前对 MySQL 数据库进行一些查询。

作为主进程中查询流的一部分,django ORM 会创建一个 sqlalchemy 连接池(如果它尚不存在)。然后创建工作进程。

芹菜作为 django 修复的一部分关闭了现有的连接。

    def close_database(self, **kwargs):
    if self._close_old_connections:
        return self._close_old_connections()  # Django 1.6
    if not self.db_reuse_max:
        return self._close_database()
    if self._db_recycles >= self.db_reuse_max * 2:
        self._db_recycles = 0
        self._close_database()
    self._db_recycles += 1

实际上,可能发生的情况是,具有一个未使用的数据库连接的sqlalchemy池对象在分叉时被复制到3个工作进程。因此,3 个不同的池有 3 个连接对象指向相同的连接文件描述符。

工作线程

在执行任务时,当要求数据库连接时,所有工作线程都会从 sqlalchemy 池中获得相同的未使用连接,因为该连接当前未使用。 所有连接都指向同一文件描述符的事实导致了MySQL连接消失错误。

之后创建的新连接都是新的,不指向相同的套接字文件描述符。

溶液:

在主流程中添加

from django.db import connection
connection.cursor()

完成任何导入之前,即在添加djorm-ext-pool模块之前。

这样,所有数据库查询都将使用由 django 在池外创建的连接。当芹菜姜戈修复关闭连接时,连接实际上被关闭,而不是回到炼金池,离开炼金池,在分叉时应付所有工人时,炼金池中没有连接。在工作人员请求数据库连接之后,sqlalchemy 返回一个新创建的连接。

相关内容

  • 没有找到相关文章

最新更新