Использование Django ORM в потоках и исключение исключения «слишком много клиентов» с помощью BoundedSemaphore - PullRequest
9 голосов
/ 08 августа 2010

Я работаю над командой 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

Я передаю экземпляр этого объекта каждому контрольному потоку, но все еще получаю «OperationalError: FATAL: извините, слишком много клиентов уже» внутри объекта Pool после запуска 120 потоков. Я ожидал, что будет открыто только 10 соединений с базой данных, и потоки будут ждать свободного слота семафора. Я могу проверить, что семафор работает, комментируя "release ()", в этом случае будут работать только 10 потоков, а другие будут ждать завершения приложения.

Насколько я понимаю, каждый поток открывает новое соединение с базой данных, даже если фактический вызов находится внутри другого потока, но почему? Есть ли способ выполнить все запросы к базе данных только в одном потоке?

1 Ответ

14 голосов
/ 09 августа 2010

ORM Django управляет соединениями с базой данных в локальных переменных потока.Таким образом, каждый отдельный поток, обращающийся к ORM, создаст свое собственное соединение.Вы можете видеть, что в первых нескольких строках django/db/backends/__init__.py.

Если вы хотите ограничить количество соединений с базой данных, вы должны ограничить количество различных потоков, которые фактически обращаются к ORM.Решением может быть реализация службы, которая делегирует запросы ORM пулу выделенных потоков ORM.Чтобы передавать запросы и их результаты из других потоков и в другие потоки, вам необходимо реализовать какой-то механизм передачи сообщений.Поскольку это типичная проблема производителя / потребителя, документы Python о многопоточности должны дать несколько советов, как этого добиться.

Редактировать: Я только что гуглил на "пул соединений django".Есть много людей, которые жалуются, что Django не обеспечивает надлежащий пул соединений.Некоторым из них удалось интегрировать отдельный пакет пула.Для PostgreSQL я бы взглянул на промежуточное ПО pgpool.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...