嗨,您的问题是您没有生成实际的 greenlet,并且 tornado.web.ascynhronous 装饰器不支持 WSGI 服务器。
但是主要逻辑是有效的,我能够让它与 HTTP 服务器一起工作(我不知道你是否绑定到 WSGI 服务器,但我想不是,因为你也可以反向代理)。
我发现很多人想在 tornado 中使用 gevent,包括我(我们在 FriendCode 使用 tornado 和gevent),所以我写了这个:
# Gevent monkeypath
from gevent import monkey
monkey.patch_all()
# Gevent imports
import gevent
# Python immports
import functools
# Tornado imports
import tornado.ioloop
import tornado.web
import tornado.httpserver
# Request imports
import requests
# Asynchronous gevent decorator
def gasync(func):
@tornado.web.asynchronous
@functools.wraps(func)
def f(self, *args, **kwargs):
#self._auto_finish = False
return gevent.spawn(func, self, *args, **kwargs)
return f
# Constants
URL_TO_FETCH = 'http://google.co.uk/'
# Global
I = 0
class MainHandler(tornado.web.RequestHandler):
@gasync
def get(self):
global I
r = requests.get(URL_TO_FETCH)
I += 1
print('Got page %d (length=%d)' % (I, len(r.content)))
self.write("Done")
self.finish()
# Our URL Mappings
handlers = [
(r"/", MainHandler),
]
def main():
# Setup app and HTTP server
application = tornado.web.Application(handlers)
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(9998)
# Start ioloop
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
在这个示例中,有两个关键部分,你做对的猴子补丁部分,然后是我写的gasync装饰器,它所做的只是将一个方法设置为异步(按照 tornado 的术语,这意味着该方法必须调用 self .finish() 本身将响应发送给客户端,因为当请求是同步的时,tornado 会自动调用它,但这不是您想要的异步)。
我希望这会有所帮助,代码在这里运行良好,我已经使用以下方法对其进行了测试:
$ ab -n 100 -c 100 http://localhost:9998/
这使 :
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient).....done
Server Software: TornadoServer/2.3
Server Hostname: localhost
Server Port: 9998
Document Path: /
Document Length: 4 bytes
Concurrency Level: 100
Time taken for tests: 0.754 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 15900 bytes
HTML transferred: 400 bytes
Requests per second: 132.67 [#/sec] (mean)
Time per request: 753.773 [ms] (mean)
Time per request: 7.538 [ms] (mean, across all concurrent requests)
Transfer rate: 20.60 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 2 4 0.8 4 5
Processing: 379 572 104.4 593 748
Waiting: 379 572 104.4 593 748
Total: 383 576 104.3 596 752
Percentage of the requests served within a certain time (ms)
50% 596
66% 640
75% 672
80% 679
90% 707
95% 722
98% 735
99% 752
100% 752 (longest request)
如您所见,总时间大致等于最长请求的时间,请记住,当 async 时:
total_time = max(all_individual_times) + n*some_overhead
其中n是请求数,而some_overhead是恒定开销。
希望有帮助:)