Асинхронный запрос COMET с Tornado и Prototype - PullRequest
9 голосов
/ 23 февраля 2010

Я пытаюсь написать простое веб-приложение с использованием библиотеки Tornado и JS Prototype. Таким образом, клиент может выполнять долгосрочную работу на сервере. Я хочу, чтобы эта работа выполнялась асинхронно - чтобы другие клиенты могли просматривать страницу и делать там что-то еще.

Вот что у меня есть:

#!/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()

Это серверная часть. Он имеет основной вид (показывает небольшое приветствие, текущее время сервера и URL-адрес для ajax-запроса, который выполняет долго выполняемое задание. Если вы нажимаете кнопку, выполняется долго выполняемое задание. И сервер зависает :( Я не могу просмотреть ни одной страницы, пока эта работа выполняется Вот шаблон страницы:

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

что я делаю не так? Как можно реализовать длинный пул, используя Tornado и Prototype (или jQuery)

PS: я посмотрел пример чата, но он слишком сложный. Не могу понять, как это работает: (

PSS Скачать полный пример

Ответы [ 4 ]

15 голосов
/ 12 марта 2010

Tornado - однопоточный веб-сервер. Ваш цикл while в методе wait_for_smith блокирует торнадо.

Вы можете переписать этот метод следующим образом:

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

Вам нужно добавить import time вверху, чтобы сделать эту работу.

1 голос
/ 26 июня 2011
function test(){
            new Ajax.Request("http://172.22.22.22:8888/longPolling",
            {
                method:"get",
                asynchronous:true,
                onSuccess: function (transport){
                    alert(transport.responseText);
                }
            })
        }

должно быть

function test(){
            new Ajax.Request("/longPolling",
            {
                method:"get",
                asynchronous:true,
                onSuccess: function (transport){
                    alert(transport.responseText);
                }
            })
        }
0 голосов
/ 25 февраля 2012

Я прочитал книгу Теда Родена "Создание пользовательского опыта в реальном времени" , и она мне очень помогла. Мне удалось создать сложную систему чата в реальном времени, используя Tornado (python). Я рекомендую прочитать эту книгу, а также "Основы сетевого программирования Python" Джона Гоерцена.

0 голосов
/ 03 августа 2010

Я преобразовал пример чата Торнадо для запуска на gevent . Взгляните на живую демонстрацию здесь и объяснение и исходный код здесь .

Он использует легкие потоки пользовательского уровня ( greenlets ) и сопоставим по скорости / использованию памяти с Tornado. Однако код прост: вы можете вызывать sleep () и urlopen () в своих обработчиках, не блокируя весь процесс, и вы можете создавать долго выполняющиеся задания, которые делают то же самое. Приложение работает асинхронно и работает от цикла событий, написанного на C ( libevent ).

Вы можете прочитать введение здесь .

...