Last active
November 29, 2016 02:54
-
-
Save lwzm/6789d667f5bb7f38547fab3e115f4e6b to your computer and use it in GitHub Desktop.
测试 tornado 的异步, 注意异步回调函数用 tornado.stack_context.wrap
还有一个协程的版本, 简直太帅了, 利用 future, 清晰明了
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment