2009-12-17 7 views
5

Recentemente ho esplorato il framework Web di Tornado per servire molte connessioni coerenti con molti client diversi.Tornado Web Framework Gestione connessione Mysql

Ho un gestore di richieste che fondamentalmente accetta una stringa crittografata RSA e la decrittografa. Il testo decrittografato è una stringa XML che viene analizzata da un gestore di documenti SAX che ho scritto. Tutto funziona perfettamente e il tempo di esecuzione (per richiesta HTTP) è stato di circa 100 millisecondi (con decodifica e analisi).

L'XML contiene l'hash Nome utente e Password dell'utente. Voglio collegarmi a un server MySQL per verificare che il nome utente corrisponda all'hash della password fornito dall'applicazione.

quando aggiungo sostanzialmente il seguente codice:

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

Il tempo necessario per eseguire la richiesta HTTP spara fino a 4 - 5 secondi! Credo che questo sia dovuto al tempo necessario per connettersi al server di database MySql stesso.

La mia domanda è: come posso accelerare? Posso dichiarare la connessione MySQL nell'ambito globale e accedervi nei gestori delle richieste creando un nuovo cursore o eseguiremo problemi di concorrenza a causa della progettazione asincrona di Tornado?

Fondamentalmente, come posso non dover sostenere una nuova connessione a un server MySQL OGNI richiesta Http, quindi richiede solo una frazione di secondo invece di più secondi da implementare.

Inoltre, si prega di notare, il server SQL è in realtà sulla stessa macchina fisica come l'istanza di Tornado Web Server

Aggiornamento

Ho appena eseguito una semplice query MySQL attraverso un profiler, lo stesso codice qui sotto.

La chiamata alla funzione 'connections.py' init ha richiesto 4.944 secondi per l'esecuzione da solo. Non sembra giusto, vero?

Update 2

credo che correre con una sola connessione (o anche un paio con un semplice piscina conn DB) sarà abbastanza veloce per gestire il throughput mi aspetto per tornado istanza del server web.

Se 1.000 client devono accedere a una query, i tempi di query tipici sono in migliaia di secondi, il client più sfortunato dovrà solo attendere un secondo per recuperare i dati.

+0

I 5 secondi possono essere correlati alla connessione al database e non alla query effettiva, se si utilizza il tornado è possibile effettuare la connessione al db a livello globale e quindi passare il parametro db con la richiesta. – chuseuiti

risposta

1

consideri SQLAlchemy, che fornisce una migliore astrazione sopra DBAPI e fornisce anche la connessione messa in comune, ecc.(Si può tranquillamente ignorare il suo ORM e basta usare la SQL-toolkit)

(Inoltre, il gioco è non fare il blocco chiamate al database nei gestori richiesta asincrona?)

+0

So che non sto facendo le chiamate di blocco nel codice sopra, se è quello che stai chiedendo, non ne ho incluso nessuno nell'esempio. Alla fine, ci sarà, ma il tempo di connessione è quello che mi sta facendo. Credo che darò una prova a SQLAlchemy, quindi grazie per la risposta! –

1

Una connessione SQL non dovrebbe richiedere 5 secondi. Cerca di non pubblicare una query e vedere se ciò migliora le tue prestazioni - che dovrebbe.

Il modulo Mysqldb ha un threadsafety di "1", il che significa che il modulo è thread-safe, ma le connessioni non possono essere condivise tra thread. È possibile implementare un pool di connessioni in alternativa.

Infine, il DBAPI ha una forma di sostituzione parametro per le query che non richiederebbero manualmente concatenare una query e fuggire parametri:

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

Beh, non sapevo nulla della procedura di parametrizzazione automatica, sarebbe davvero d'aiuto. Vedrò di rimuovere la query domani e vedere dove mi lascia. Penso che dovrò finire per scrivere un pool di connessioni ... solo perché c'è la possibilità che le chiamate al DB blocchino altri thread. Sarà in prova se deciderò di farlo o meno. –

0

dichiararla nel gestore di base, lo farà essere chiamato una volta per applicazione.