Я работаю над командой 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: ФАТАЛЬНЫЙ: извините, слишком много клиентов уже" в объекте Пула после init-луга 120 потоков. Я ожидал, что только 10 соединений с базой данных будут открыты, и потоки будут ожидать свободного семафорного слота. Я могу проверить, что семафор работает путем комментария "выпуска ()", в этом случае только 10 потоков будут работать, и другой будет ожидать до завершения приложения.
Так, как я понимаю, каждый поток открывает новое соединение с базой данных, даже если фактический вызов является внутренним другим потоком, но почему? Там какой-либо путь состоит в том, чтобы выполнить все запросы базы данных только в одном потоке?
ORM Django управляет подключениями к базе данных в локальных переменных потока. Таким образом, каждый отдельный поток, обращающийся к ORM, будет создавать свое собственное соединение. Вы можете видеть это в первых нескольких строках django / db / backends / __ init __. Py
.
Если вы хотите ограничить количество подключений к базе данных, вы должны ограничить количество различных потоков, которые фактически обращаются к ORM. Решением может быть реализация службы, которая делегирует запросы ORM пулу выделенных потоков ORM. Чтобы передавать запросы и их результаты из других потоков и в другие потоки, вам необходимо реализовать какой-то механизм передачи сообщений. Поскольку это типичная проблема производителя / потребителя, документация Python о многопоточности должна дать некоторые подсказки, как этого добиться.
Изменить: Я только что поискал в Google "пул соединений django". Многие люди жалуются, что Django не предоставляет правильный пул соединений. Некоторым из них удалось интегрировать отдельный пул-пакет. Что касается PostgreSQL, я бы посмотрел на промежуточное ПО pgpool.