2013-02-12 5 views
5

Sto eseguendo un'applicazione Flask su Heroku usando gunicorn con gli operatori di eventlet. Un percorso particolare sulla mia app riceve spesso dati POST (x-www-form-urlencoded) con alcuni campi piuttosto pesanti - dell'ordine di 500 KB al massimo.Flask on Heroku: request.form è incredibilmente lento con grandi dati POST?

Questo funziona bene quando funziona a livello locale, ma su Heroku, chiede a quel percorso impiega da 5 a 30 secondi per completare - e quasi il 100% del tempo viene speso nel primo accesso al Request.Form:

t = time.time() 
action = str(request.form['action']) 
dt = time.time() - t # Often 10 seconds or more! 

Ciò è confermato anche dalla traccia di richiesta lenta Newrelic. Ci sono alcuni millisecondi qui o là per le operazioni del database, e quindi un'enorme quantità di tempo nel codice Python, apparentemente trascorsa in attesa su qualche I/O, poiché il tempo di CPU segnalato è in genere inferiore a un millisecondo.

Sono stato completamente incapace di riprodurre questo in un ambiente locale utilizzando la stessa configurazione gunicorn/eventlet che sto usando in produzione. Anche il server WSGI di debug integrato è velocissimo su queste richieste.

Qualcuno ha idea di cosa potrebbe andare storto? E 'un problema con Flask, o qualcosa su cui ho solo bisogno di contattare il supporto di Heroku?

+2

Hai provato a mettere l'app sulla sandbox gratuita di dotcloud? L'ho usato per una piccola app Flask di recente, ed è stato semplice. Forse testare la tua app lì o in qualche luogo simile per vedere se è possibile isolare il problema con Heroku o con Flask o la tua app? –

+1

I second @AllanAnderson - prova una configurazione simile su un altro fornitore - se si interrompe allo stesso modo potresti fornire alcuni dati di esempio che causano il problema? –

+2

* "e quasi il 100% del tempo è trascorso nel primo accesso a request.form" * È possibile che tu stia sperimentando gli effetti del dyno idling? https://devcenter.heroku.com/articles/dynos#dyno-idling – Dominic

risposta

3

Penso di aver capito esattamente cosa stava succedendo. TL; DR non era affatto lento sul lato server, sono stato semplicemente ingannato dai tempi di risposta riportati da Newrelic!

Ho provato a eseguire lo stesso codice sulla sandbox di dotCloud come suggerito da @ AllanAnderson. Ho creato per la prima volta un caso di test ridotto: un semplice modulo HTML con alcuni campi nascosti pre-caricati con circa 900 KB di dati e una funzione di visualizzazione che non fa altro che leggere dal dizionario request.form e misurare il tempo trascorso per ogni accesso utilizzando time.time().

Su Heroku, i risultati si presentava così:

5.87100 seconds: read field "p1": 786432 bytes 
0.00019 seconds: read field "p2": 131072 bytes 
0.00003 seconds: read field "p3": 12288 bytes 
0.00001 seconds: read field "p4": 1024 bytes 

E su dotCloud:

0.00096 seconds: read field "p1": 786432 bytes 
0.00019 seconds: read field "p2": 131072 bytes 
0.00003 seconds: read field "p3": 12288 bytes 
0.00001 seconds: read field "p4": 1024 bytes 

Tuttavia, entrambe le prove sembrava prendere la stessa quantità di tempo nel mio browser ... e ormai hai probabilmente indovinato la vera risposta a questo "problema". :-)

Si scopre che Gunicorn su Heroku stava eseguendo la funzione di visualizzazione non appena sono state ricevute le intestazioni e il primo accesso a request.form bloccato fino a quando non è stato ricevuto il resto della richiesta. Quindi Newrelic ha visto tutti questi tempi di risposta ridicolmente lenti che erano in realtà solo il risultato del caricamento dei dati POST su una connessione di rete scadente. Apparentemente, la configurazione di dotCloud attende solo che sia stata ricevuta l'intera richiesta.

Ciò rende le metriche di Newrelic meno utili, ma in realtà non è un problema con l'esperienza dell'utente finale.

+0

Felice di sentire che hai risolto ciò che stava fuorviando le tue metriche. Yay processo di eliminazione! –

Problemi correlati