在线程中使用Django ORM并通过使用BoundedSemaphore避免"太多客户端"异常

Riz*_*Riz 10 django postgresql orm multithreading 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
Run Code Online (Sandbox Code Playgroud)

我将此对象的实例传递给每个检查线程,但在初始化120个线程后,仍然在Pool对象内部获得"OperationalError:FATAL:抱歉,已经有太多客户端"了.我预计只会打开10个数据库连接,线程将等待免费的信号量插槽.我可以通过注释"release()"来检查信号量的工作原理,在这种情况下,只有10个线程可以工作,其他线程将等到应用程序终止.

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

Ber*_*ohn 14

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

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

编辑:我刚刚用Google搜索"django连接池".有很多人抱怨Django没有提供适当的连接池.其中一些设法集成了一个单独的池包.对于PostgreSQL,我会看一下pgpool中间件.

  • 从 1.6 左右开始,我们可以在 Django 中建立持久连接,看看 https://docs.djangoproject.com/en/1.8/ref/settings/#conn-max-age (2认同)