2010-02-23 15 views
9

estoy tratando de escribir sencilla aplicación web usando la biblioteca del tornado y JS Prototipo. Entonces, el cliente puede ejecutar un trabajo de larga ejecución en el servidor. Deseo que este trabajo se ejecute de forma asincrónica, para que otros clientes puedan ver la página y hacer algunas cosas allí.consulta asincrónica COMET con Tornado y Prototipo

Aquí lo que tengo:

#!/usr/bin/env/ pytthon 

import tornado.httpserver 
import tornado.ioloop 
import tornado.options 
import tornado.web 
from tornado.options import define, options 

import os 
import string 
from time import sleep 
from datetime import datetime 

define("port", default=8888, help="run on the given port", type=int) 

class MainHandler(tornado.web.RequestHandler): 
    def get(self): 
     self.render("templates/index.html", title="::Log watcher::", c_time=datetime.now()) 

class LongHandler(tornado.web.RequestHandler): 
    @tornado.web.asynchronous 
    def get(self): 
     self.wait_for_smth(callback=self.async_callback(self.on_finish)) 
     print("Exiting from async.") 
     return 

    def wait_for_smth(self, callback): 
     t=0 
     while (t < 10): 
      print "Sleeping 2 second, t={0}".format(t) 
      sleep(2) 
      t += 1 
     callback() 

    def on_finish(self): 
     print ("inside finish") 
     self.write("Long running job complete") 
     self.finish() 



def main(): 
    tornado.options.parse_command_line() 

    settings = { 
     "static_path": os.path.join(os.path.dirname(__file__), "static"), 
     } 

    application = tornado.web.Application([ 
     (r"/", MainHandler), 
     (r"/longPolling", LongHandler) 
     ], **settings 
    ) 
    http_server = tornado.httpserver.HTTPServer(application) 
    http_server.listen(options.port) 
    tornado.ioloop.IOLoop.instance().start() 


if __name__ == "__main__": 
    main() 

Esto es parte del servidor. Tiene una vista principal (muestra un pequeño saludo, la hora actual del servidor y la url para la consulta ajax, que ejecuta un trabajo de larga ejecución. Si presiona un botón, se ejecutará una tarea larga. Y el servidor se bloquea :(No puedo ver ninguna página, . este trabajo se está ejecutando Aquí está la página de plantilla:

<html> 
<head> 
    <title>{{ title }}</title> 

    <script type="text/javascript" language="JavaScript" src="{{ static_url("js/prototype.js")}}"></script> 


    <script type='text/javascript' language='JavaScript'> 
     offset=0 
     last_read=0 

     function test(){ 
      new Ajax.Request("http://172.22.22.22:8888/longPolling", 
      { 
       method:"get", 
       asynchronous:true, 
       onSuccess: function (transport){ 
        alert(transport.responseText); 
       } 
      }) 
     } 


    </script> 
</head> 
<body> 
    Current time is {{c_time}} 
    <br> 
    <input type="button" value="Test" onclick="test();"/> 
</body> 
</html> 

lo que estoy haciendo mal ¿Cómo se puede aplicar a largo puesta en común, el uso de Tornado y Prototipo (o jQuery)

PS:? he mirado ejemplo de chat , pero es demasiado complicado. No puedo entender cómo funciona :(

PSS Descargar completo example

Respuesta

15

Tornado es el servidor web de un solo subproceso. Su ciclo while en el método wait_for_smith está bloqueando a Tornado.

Puede volver a escribir ese método como este:

def wait_for_smth(self, callback, t=10): 
    if t: 
     print "Sleeping 2 second, t=%s" % t 
     tornado.ioloop.IOLoop.instance().add_timeout(time.time() + 2, lambda: self.wait_for_smth(callback, t-1)) 
    else: 
     callback() 

es necesario agregar import time en la parte superior para hacer este trabajo.

+0

que he probado ese método y puede confirmar que ya no se cuelga, pero ahora el programa muestra un cuadro de alerta donde responseText no está definida y hay un error 405. – brainysmurf

+0

Hablé demasiado rápido, el problema estaba en mi extremo ... Tenía dos direcciones diferentes especificadas. Esto definitivamente funciona – brainysmurf

+0

Pero, ¿es esta larga encuesta? Parece simplemente sondeándome. Eso sí, soy un novato de Tornado/Comet. – Lorenzo

0

me he convertido, como charla de Tornado para ejecutarse en gevent. Eche un vistazo a the live demo here y the explanation and source code here.

que utiliza hilos a nivel de usuario ligero (greenlets) y es comparable en uso velocidad/memoria con Tornado. Sin embargo, el código es sencillo, puede llamar a sleep() y urlopen() en sus controladores sin bloquear todo el proceso y puede generar trabajos de larga ejecución que hagan lo mismo. Debajo del capó, la aplicación es asíncrona, impulsada por un ciclo de eventos escrito en C (libevent).

Puede leer el introduction here.

+0

Niza tenedor Denis ... – securecurve

1
function test(){ 
      new Ajax.Request("http://172.22.22.22:8888/longPolling", 
      { 
       method:"get", 
       asynchronous:true, 
       onSuccess: function (transport){ 
        alert(transport.responseText); 
       } 
      }) 
     } 

debería haber

function test(){ 
      new Ajax.Request("/longPolling", 
      { 
       method:"get", 
       asynchronous:true, 
       onSuccess: function (transport){ 
        alert(transport.responseText); 
       } 
      }) 
     } 
+0

en el caso de puertos no predeterminados, se debe pasar toda la ruta. – securecurve