Код блокировки торнадо

Я только что подумал о неблокирующей инфраструктуре торнадо и программировании, управляемом событиями. На самом деле я пишу простое веб-приложение, которое обращается к HTTP-API внешнего веб-сервиса. Я понимаю, почему я должен называть этот API неблокирующим. Но есть ли недостатки, если я сделаю только первый вызов неблокирующим, чтобы IOLoop мог зацикливаться дальше?

Например:

@tornado.web.asynchronous
def get(self):
    nonblocking_call1(self._callback)

def _callback(self, response):
    self.write(str(response))
    self.write(str(blocking_call2()))
    self.write(str(blocking_call3()))
    self.finish()

vs.

@tornado.web.asynchronous
def get(self):
    nonblocking_call1(self._nonblocking_callback1)

def _callback1(self, response):
    self.write(str(response))
    nonblocking_call2(self._nonblocking_callback2)

def _callback2(self, response):
    self.write(str(response))
    nonblocking_call3(self._nonblocking_callback3)

def _callback3(self, response):
    self.write(str(response))
    self.finish()

person Georg Jung    schedule 24.03.2012    source источник


Ответы (1)


Если вы используете блокирующий код внутри торнадо, тот же процесс торнадо не сможет обрабатывать любые другие запросы, пока какой-либо блокирующий код находится в ожидании. Ваше приложение не будет поддерживать более одного пользователя одновременно, и даже если блокирующий вызов займет всего около 100 мс, это все равно будет ОГРОМНЫМ убийцей производительности.

Если для вас это утомительно (для меня это утомительно), вы можете использовать модуль tornado gen:

class GenAsyncHandler(RequestHandler):
    @asynchronous
    @gen.engine
    def get(self):
        http_client = AsyncHTTPClient()
        response = yield gen.Task(http_client.fetch, "http://example.com")
        do_something_with_response(response)
        self.render("template.html")
person Not_a_Golfer    schedule 24.03.2012