django - 在线程中使用 Django ORM 并通过使用 BoundedSemaphore 避免 "too many clients"异常

标签 django multithreading postgresql orm connection-pooling

我使用 manage.py 命令创建大约 200 个线程来检查远程主机。我的数据库设置允许我使用 120 个连接,所以我需要使用某种池。我试过使用单独的线程,像这样

class Pool(Thread):
    def __init__(self):
        Thread.__init__(self)        
        self.semaphore = threading.BoundedSemaphore(10)

    def give(self, trackers):
        self.semaphore.acquire()
        data = ... some ORM (not lazy, query triggered here) ...
        self.semaphore.release()
        return data

我将此对象的实例传递给每个检查线程,但在初始化 120 个线程后仍然在 Pool 对象中出现“OperationalError: FATAL: sorry, too many clients already”。 我预计只会打开 10 个数据库连接,并且线程会等待空闲的信号量槽。我可以通过注释“release()”来检查信号量是否工作,在这种情况下,只有 10 个线程可以工作,其他线程将等到应用程序终止。

据我所知,即使实际调用是在不同的线程中,每个线程都会打开与数据库的新连接,但为什么呢?有没有办法在一个线程内执行所有数据库查询?

最佳答案

Django 的 ORM 在线程局部变量中管理数据库连接。因此,访问 ORM 的每个不同线程都将创建自己的连接。您可以在 django/db/backends/__init__.py 的前几行中看到这一点。

如果要限制建立的数据库连接数,则必须限制实际访问 ORM 的不同线程数。一个解决方案可能是实现一个服务,将 ORM 请求委托(delegate)给一个专用的 ORM 线程池。要将请求及其结果从其他线程传输到其他线程,您将必须实现某种消息传递机制。由于这是一个典型的生产者/消费者问题,关于线程的 Python 文档应该给出一些如何实现这一点的提示。

编辑: 我刚刚在 google 上搜索了“django 连接池”。有很多人提示 Django 没有提供合适的连接池。他们中的一些人设法集成了一个单独的池包。对于 PostgreSQL,我会看一下 pgpool 中间件。

关于django - 在线程中使用 Django ORM 并通过使用 BoundedSemaphore 避免 "too many clients"异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3435673/

相关文章:

python - 从第三方 api 返回项目列表的 DRF 方式是什么?

c# - Monitor.Enter 和 Monitor.Exit 在不同的线程中

java - 同步异步任务的最佳方式

sql - 将同一个表中的 2 个 SQL 查询合并为单个输出

python - 扩展 Django Flatpages 以接受模板标签

python - 为什么我们需要 Celery 中的签名?

c - 如何强制程序使用未对齐的地址?

java - 组织.postgresql.util.PSQLException : No value specified for parameter 1

php - 如何在登录表单中不区分用户名大小写?

python - 带有普通 Django 表单和 Bootstrap 的 Django-CKEditor