Может ли один класс Tornado RequestHandler
принимать новые запросы, ожидая завершения Future
в одном из своих экземпляров?
Я отлаживал сопрограмму Tornado, которая вызывала ThreadPoolExecutor
, и заметил, что пока сопрограмма ждала завершения исполнителя, RequestHandler
была заблокирована. Таким образом, любые новые запросы к этому обработчику ожидают завершения сопрограммы.
Вот код, который я написал, чтобы воспроизвести свое наблюдение:
from time import sleep
from concurrent.futures import ThreadPoolExecutor
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.web import Application, RequestHandler
from tornado.gen import coroutine
class Handler1(RequestHandler):
@coroutine
def get(self):
print('Setting up executor ...')
thread_pool = ThreadPoolExecutor(1)
print('Yielding ...')
yield thread_pool.submit(sleep, 30)
self.write('Ready!')
print('Finished!')
app = Application([('/1$', Handler1)])
app.listen(8888)
PeriodicCallback(lambda: print('##'), 10000).start()
IOLoop.instance().start()
Теперь, если я дважды обращаюсь к localhost:8888/1
, я получаю следующий вывод:
##
Setting up executor ...
Yielding ...
##
##
##
Finished!
Setting up executor ...
Yielding ...
##
##
##
Finished!
##
Но я ожидаю, что произойдет следующее:
##
Setting up executor ...
Yielding ...
Setting up executor ...
Yielding ...
##
##
##
Finished!
Finished!
##
Обратите внимание, что блокируется только RequestHandler
, потому что мы по-прежнему получаем ##
каждые 10 секунд. На самом деле, если вы добавите еще один идентичный RequestHandler
(Handler2) и получите доступ к localhost:8888/1
и localhost:8888/2
, это приведет к ожидаемому результату.
Это нормально? Это предполагаемое поведение?
Извините за мой плохой английский.