<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">2014-03-13 19:35 GMT+01:00 Balan Victor <span dir="ltr"><<a href="mailto:balan.victor0@gmail.com" target="_blank">balan.victor0@gmail.com</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Di recente ho letto un po di tornado, e in particolare mi sono soffermato sul modulo tornado.httpserver(Non-blocking HTTP server). Stando a quello che c'è scritto sulla documentazione ufficiale parla di "non-blocking, single-threaded HTTP server" e di risolvere il problemi di tipo C10K. Qua sembra interessante, anche se non ho la minima idea di come funzioni.</div>
</blockquote><div>> [...]</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Detto questo, non riesco a capire l'utilità di un HTTP Server con performance elevatissime ma che non permetta una minima interazione con il database.</div>
<div><br></div></div></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div></div><div>Probabilmente sopra ho scritto delle cavolate ma mi mancano completamente le basi per questo tipo di argomenti e volevo capire meglio come funzionano e quali sono i campi di applicazione di tecnologie simili.</div>
</div>
<br></blockquote><div><br></div><div>L'argomento è complesso.</div><div>Nel caso di un server C10K ready ci sono due aspetti principali.</div><div>Il primo riguarda tutto quel codice che esegue una richiesta ed aspetta una risposta.</div>
<div>Il secondo riguarda il paradigma utilizzato per gestire il flusso del codice.</div><div><br></div><div>Il 97.7% delle librerie disponibili fa qualcosa del tipo:</div><div><br></div><div> >>> status = send_request(data)</div>
<div> >>> resp = recv_response()</div><div><br></div><div>Entrambe le funzioni potrebbero metterci molto tempo a completare, ma questo codice blocca l'intero thread fino a quando resp non è disponibile.</div>
<div><br></div><div>Quello che fa tornado è di usare quelle che si chiamano coroutine, o threading cooperativo.</div><div>In questo caso sia send_request che recv_response bloccano il flusso corrente del codice (la coroutine corrente), ma non l'intero thread perchè usando le coroutine viene effettuato un salto (simile al goto) che va ad eseguire altre funzioni coroutine.</div>
<div><br></div><div>Senza le coroutine, quello che si fa è usare le callback ed una macchina a stati (lo stato deve essere gestito manualmente perchè non hai lo stack disponibile nel codice "normale").</div><div>
<br></div><div>L'esempio di prima diventa:</div><div><br></div><div> >>> def do_request(data, ctx):</div><div> >>> send_request(data, on_request_done, ctx)</div><div> >>></div><div> >>> def on_request_done(status, ctx):</div>
<div> >>> recv_response(on_response_done, ctx)</div><div> >>> </div><div> >>> def on_response_done(resp, ctx):</div><div> >>> # DONE</div><div><br></div><div>Come vedi diventa molto complicato, specialmente se ad esempio devi fare il parsing di un protocollo come HTTP (puoi vedere il codice di Twisted se ti interessa).</div>
<div><br></div><div>Tra l'altro il motivo perchè tornado va di moda è perchè permette di avere il codice che è praticamente lo stesso di quello "normale", ma che si comporta in modo completamente diverso. Twisted offre un framework per la programmazione asincrona da anni, ma non è mai stato di moda, perchè molto più difficile.</div>
<div><br></div><div>Considerato tutti i problemi che gli utenti hanno con tornado e friends (e che nemmeno sanno di sapere), direi che, come sempre, "explicit is better than implicit".</div><div><br></div><div>Il mio suggerimento è sempre quello di imparare prima le basi (vicino a quello che realmente succede) e solo dopo utilizzare cose che rendono la programmazione e manutenzione più semplice.</div>
<div><br></div><div>Come ultima cosa: gevent (l'implementazione delle coroutine) sembra risolva tutti i problemi, ma in realtà tutto quello che fa ha un costo. Non è un caso che i web server C10K usano la programmazione tramite callback e macchina a stati; questo perchè è molto più efficiente nella gestione della memoria. Ogni coroutine è come un thread ed ha bisogno di memoria per lo stack, oltre poi al costo per il context switch.</div>
<div><br></div><div><br></div><div>Ciao Manlio</div></div></div></div>