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))
Объявите его в базовом обработчике, он будет вызываться один раз для каждого приложения.