Используя Django ORM в потоках и избегающий “слишком многих клиентов” исключение при помощи BoundedSemaphore

Я работаю над командой 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 потоков будут работать, и другой будет ожидать до завершения приложения.

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

10
задан Riz 8 August 2010 в 19:10
поделиться

1 ответ

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

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

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

14
ответ дан 3 December 2019 в 23:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: