lwzm
10/31/2016 - 2:51 AM

测试 tornado 的异步, 注意异步回调函数用 tornado.stack_context.wrap 还有一个协程的版本, 简直太帅了, 利用 future, 清晰明了

测试 tornado 的异步, 注意异步回调函数用 tornado.stack_context.wrap 还有一个协程的版本, 简直太帅了, 利用 future, 清晰明了

#!/usr/bin/env python3

import threading
import time
import concurrent.futures

import requests


local = threading.local()


def get(url):
    try:
        session = local.session
    except AttributeError:
        session = local.session = requests.Session()
    resp = session.get(url)
    assert resp.status_code < 400
    return resp.text


def main():
    n = 100
    pool = concurrent.futures.ThreadPoolExecutor(n)
    futures = [pool.submit(get, "http://localhost:1111/{}".format(1))
               for i in range(n)]
    time.sleep(0.3)
    get("http://localhost:1111/_/1")
    print(futures)
    for future in concurrent.futures.as_completed(futures):
        print(future.result())
    pool.shutdown()


def main2():
    n = 100

    cli = tornado.httpclient.AsyncHTTPClient(max_clients=50)

    @tornado.gen.coroutine
    def f1():
        x = yield cli.fetch("http://localhost:1111/1")
        print(x.body.decode())

    io_loop = tornado.ioloop.IOLoop.current()

    for i in range(n):
        io_loop.spawn_callback(f1)

    @tornado.gen.coroutine
    def f2():
        for _ in range(n // cli.max_clients + 1):
            yield tornado.gen.sleep(0.3)
            get("http://localhost:1111/_/1")
        yield tornado.gen.sleep(0.1)
        io_loop.stop()

    io_loop.spawn_callback(f2)

    io_loop.start()


if __name__ == "__main__":
    main()
#!/usr/bin/env python3

import collections

import tornado.concurrent
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.gen


class Base(tornado.web.RequestHandler):
    def set_default_headers(self):
        self.set_header("Content-Type", "text/plain; charset=UTF-8")
        self.set_header("Cache-Control", "no-store")


class Handler(Base):
    _futures = collections.defaultdict(list)

    @classmethod
    def to(cls, token, msg):
        lst = cls._futures[token]
        while lst:
            lst.pop().set_result(msg)

    @tornado.gen.coroutine
    def get(self, token):
        future = tornado.concurrent.Future()
        self._futures[token].append(future)
        result = yield future
        self.write(result)


class Handler2(Base):
    def get(self, token):
        Handler.to(token, "hi")
        self.write(token)


application = tornado.web.Application([
    (r"/_/(.+)", Handler2),
    (r"/(.+)", Handler),
], static_path="static", template_path="templates", debug=True)


if __name__ == "__main__":
    import tornado.options
    tornado.options.parse_command_line()
    application.listen(1111, xheaders=True)
    tornado.ioloop.IOLoop.instance().start()
#!/usr/bin/env python3

import collections

import tornado.concurrent
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.gen
import tornado.stack_context


class Handler(tornado.web.RequestHandler):
    _queues = collections.defaultdict(collections.deque)
    _callbacks = {}

    def set_default_headers(self):
        self.set_header("Content-Type", "text/plain; charset=UTF-8")
        self.set_header("Cache-Control", "no-store")

    @classmethod
    def to(cls, token, msg):
        q = cls._queues[token]
        q.append(msg)
        cls._flush(token)

    @classmethod
    def _flush(cls, token):
        f = cls._callbacks.pop(token, None)
        if f:
            f()

    @tornado.web.asynchronous
    def get(self, token):
        q = self._queues[token]
        def f():
            if q:
                self.finish(q.popleft())
            else:
                self.set_status(204)
                self.finish()
        if q:
            f()
        else:
            self._flush(token)
            assert token not in self._callbacks  # after _flush
            self._callbacks[token] = tornado.stack_context.wrap(f)


class Handler2(tornado.web.RequestHandler):
    def get(self, token):
        Handler.to(token, "hi")

 
application = tornado.web.Application([
    (r"/_/(.+)", Handler2),
    (r"/(.+)", Handler),
], debug=True)
 

if __name__ == "__main__":
    import tornado.options
    tornado.options.parse_command_line()
    application.listen(1111, xheaders=True)
    tornado.ioloop.IOLoop.instance().start()