我正在尝试测试龙卷风中的异步处理,我编写了一个HTTP服务器,用于计算递归HTTP调用的斐波纳契数。 它适用于像6这样的小数字,但挂在8。 我确信异步在这里工作,否则它会卡在n = 3。 我无法解释为什么它停留在8.斐波那契增长很快但是8它仍然没有太多的耗尽端口或打开文件处理程序。
这里有什么障碍?
python 2.7和龙卷风4.3
import tornado.ioloop
import tornado.web
from tornado import gen
from tornado.httpclient import AsyncHTTPClient
class MainHandler(tornado.web.RequestHandler):
http_client = AsyncHTTPClient()
@gen.coroutine
def get(self):
n = int(self.get_argument('n', 1))
print 'n = ', n
if n <= 2:
self.write("1")
else:
npUrl = 'http://localhost:8888/?n=%s' % (n - 1)
nppUrl = 'http://localhost:8888/?n=%s' % (n - 2)
print " get np %s an npp %s " % (npUrl, nppUrl)
np, npp = yield [ self.http_client.fetch(npUrl),
self.http_client.fetch(nppUrl) ]
npAndNpp = int(np.body) + int(npp.body)
print 'np + npp = %s + %s = %s' % (np.body, npp.body, npAndNpp)
self.write("%s" % npAndNpp)
# raise tornado.gen.Return(None)
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
记录输出
egnyte@diehard:~/demo/tornado$ python async-fibonacci.py
n = 7
get np http://localhost:8888/?n=6 an npp http://localhost:8888/?n=5
n = 6
get np http://localhost:8888/?n=5 an npp http://localhost:8888/?n=4
n = 5
get np http://localhost:8888/?n=4 an npp http://localhost:8888/?n=3
n = 5
get np http://localhost:8888/?n=4 an npp http://localhost:8888/?n=3
n = 4
get np http://localhost:8888/?n=3 an npp http://localhost:8888/?n=2
n = 4
get np http://localhost:8888/?n=3 an npp http://localhost:8888/?n=2
n = 3
get np http://localhost:8888/?n=2 an npp http://localhost:8888/?n=1
n = 4
get np http://localhost:8888/?n=3 an npp http://localhost:8888/?n=2
n = 3
get np http://localhost:8888/?n=2 an npp http://localhost:8888/?n=1
n = 3
get np http://localhost:8888/?n=2 an npp http://localhost:8888/?n=1
n = 2
n = 3
get np http://localhost:8888/?n=2 an npp http://localhost:8888/?n=1
n = 7
get np http://localhost:8888/?n=6 an npp http://localhost:8888/?n=5
ERROR:tornado.application:Multiple exceptions in yield list
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/tornado/gen.py", line 789, in callback
result_list.append(f.result())
File "/usr/local/lib/python2.7/dist-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "<string>", line 3, in raise_exc_info
HTTPError: HTTP 599: Timeout
ERROR:tornado.application:Multiple exceptions in yield list
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/tornado/gen.py", line 789, in callback
result_list.append(f.result())
File "/usr/local/lib/python2.7/dist-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "<string>", line 3, in raise_exc_info
HTTPError: HTTP 599: Timeout
ERROR:tornado.application:Multiple exceptions in yield list
答案 0 :(得分:2)
您的程序递归要求Tornado同时保留10个以上的HTTP请求,但默认情况下,AsyncHTTPClient的max_clients为10。
当您开始第11次请求时,您的程序会死锁:它需要启动一个新的HTTP请求才能完成Fibonacci计算,但是在当前请求之一完成之前它无法启动新的请求。
如果添加以下行,您可以看到这一点:
import tornado.options
tornado.options.parse_command_line()
使用--logging=debug
开始您的计划。最终您的程序会记录:
[D 160326 12:03:16 simple_httpclient:137] max_clients limit reached, request queued. 10 active, 11 queued requests.
......然后死锁。二十秒后,AsyncHTTPClient的默认超时会引发异常。
您可以通过在程序开头运行此程序来支持更高级别的递归:
AsyncHTTPClient.configure(None, max_clients=100)