Tornado Web Framework Mysql обработка соединений

Недавно я изучал веб-фреймворк Tornado, чтобы обслуживать множество последовательных соединений с множеством разных клиентов.

У меня есть обработчик запросов, который в основном берет зашифрованную строку RSA и расшифровывает ее. Расшифрованный текст - это строка XML, которая анализируется обработчиком документов SAX, который я написал. Все отлично работает, и время выполнения (на HTTP-запрос) составляло примерно 100 миллисекунд (с расшифровкой и анализом).

XML содержит имя пользователя и хэш пароля пользователя. Я хочу подключиться к серверу MySQL, чтобы убедиться, что имя пользователя соответствует хэшу пароля, предоставленному приложением.

Когда я добавляю в основном следующий код:

conn = MySQLdb.connect (host = "192.168.1.12",
                user = "<useraccount>",
                passwd = "<Password>",
                db = "<dbname>")
    cursor = conn.cursor()

    safe_username = MySQLdb.escape_string(XMLLoginMessage.username)
    safe_pass_hash = MySQLdb.escape_string(XMLLoginMessage.pass_hash)

    sql = "SELECT * FROM `mrad`.`users` WHERE `username` = '" + safe_username + "' AND `password` = '" + safe_pass_hash + "' LIMIT 1;"

    cursor.execute(sql)

            cursor.close()
    conn.close()

Время выполнения HTTP-запроса достигает 4 - 5 секунд! Я считаю, что это происходит за время, необходимое для подключения к самому серверу базы данных MySql.

Мой вопрос, как я могу ускорить это? Могу ли я объявить соединение MySQL в глобальной области и получить к нему доступ в обработчиках запросов, создав новый курсор, или возникнут проблемы с параллелизмом из-за асинхронного проектирования Tornado?

По сути, как я могу не устанавливать новое соединение с сервером MySQL КАЖДЫЙ Http-запрос, поэтому его реализация занимает доли секунды, а не несколько секунд.

Также обратите внимание, что SQL-сервер фактически находится на том же физическом компьютере, что и экземпляр Tornado Web Server.

Обновить

Я просто запустил простой запрос MySQL через профилировщик, тот же код ниже.

Вызов функции init 'connections.py' занял 4,944 секунды, чтобы выполнить в одиночку. Это не кажется правильным, не так ли?

Обновление 2

Я думаю, что запуск с одним соединением (или даже с несколькими с очень простым пулом соединения с БД) будет достаточно быстрым, чтобы справиться с пропускной способностью, которую я ожидаю для каждого экземпляра веб-сервера торнадо.

Если 1000 клиентов нуждаются в доступе к запросу, типичное время запроса составляет тысячи секунд, то самому неудачливому клиенту потребуется только одна секунда, чтобы получить данные.

3 ответа

Решение

Рассмотрим SQLAlchemy, который обеспечивает более качественную абстракцию по сравнению с DBAPI, а также обеспечивает пул соединений и т. Д. (Вы можете с радостью проигнорировать его ORM и просто использовать SQL-инструментарий)

(Кроме того, вы не блокируете вызовы базы данных в асинхронных обработчиках запросов?)

Соединение SQL не должно занимать 5 секунд. Постарайтесь не выдавать запрос и посмотрите, не улучшит ли это вашу производительность - что и должно.

Модуль Mysqldb имеет потокобезопасность "1", что означает, что модуль является потокобезопасным, но соединения не могут быть разделены между потоками. Вы можете реализовать пул соединений в качестве альтернативы.

Наконец, DB-API имеет форму замены параметров для запросов, которые не требуют ручной конкатенации запроса и экранирования параметров:

cur.execute("SELECT * FROM blach WHERE x = ? AND y = ?", (x,y))

Объявите его в базовом обработчике, он будет вызываться один раз для каждого приложения.

Другие вопросы по тегам