Pergunta

Recentemente, tenho explorado a estrutura da web de tornados para atender muitas conexões consistentes por muitos clientes diferentes.

Eu tenho um manipulador de solicitação que basicamente pega uma corda criptografada da RSA e a descriptografa. O texto descriptografado é uma string xml que é analisada por um manipulador de documentos sax que eu escrevi. Tudo funciona perfeitamente bem e o tempo de execução (por solicitação HTTP) foi de aproximadamente 100 milissegundos (com descriptografia e análise).

O XML contém o hash de nome de usuário e senha do usuário. Quero conectar -me a um servidor MySQL para verificar se o nome de usuário corresponde ao hash de senha fornecido pelo aplicativo.

Quando eu adiciono basicamente o seguinte código:

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()

O tempo necessário para executar a solicitação HTTP dispara até 4 a 5 segundos! Acredito que isso está incorrido no tempo necessário para se conectar ao próprio servidor de banco de dados MySQL.

Minha pergunta é como posso acelerar isso? Posso declarar a conexão MySQL no escopo global e acessá -la nos manipuladores de solicitação, criando um novo cursor, ou que terá problemas de concorrência devido ao design assíncrono do tornado?

Basicamente, como posso não ter que incorrer em uma nova conexão com um servidor MySQL a cada solicitação HTTP, para que seja necessária apenas uma fração de segundo em vez de vários segundos para implementar.

Além disso, observe que o servidor SQL está na mesma máquina física que a instância do servidor da web de tornado

Atualizar

Acabei de executar uma consulta MySQL simples através de um perfilador, o mesmo código abaixo.

A chamada para 'conexão.py' iniciar A função levou 4,944 segundos para executar sozinha. Isso não parece certo, não é?

Atualização 2

Eu acho que executar com uma conexão (ou até alguns com um pool de conn DB muito simples) será rápido o suficiente para lidar com a taxa de transferência que estou esperando por instância do Tornado Web Server.

Se 1.000 clientes precisarem acessar uma consulta, os tempos de consulta típicos estão nos milhares de segundos, o cliente mais infeliz precisaria esperar um segundo para recuperar os dados.

Foi útil?

Solução

Considerar Sqlalchemy, que fornece uma abstração mais agradável sobre o DBAPI e também fornece pool de conexões etc. (você pode ignorar com prazer seu ORM e apenas usar o SQL-Toolkit)

(Além disso, você não está fazendo chamadas de banco de dados de bloqueio nos manipuladores de solicitação assíncronos?)

Outras dicas

Uma conexão SQL não deve levar 5 segundos. Tente não emitir uma consulta e ver se isso melhora seu desempenho - o que deveria.

O módulo MySQLDB possui uma segurança de threads de "1", o que significa que o módulo é seguro, mas as conexões não podem ser compartilhadas entre os threads. Você pode implementar um pool de conexões como alternativa.

Por fim, o DB-API possui um formulário de substituição de parâmetros para consultas que não exigiriam concatenando manualmente uma consulta e os parâmetros de escape:

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

Declare -o no manipulador de base, ele será chamado uma vez por aplicativo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top