Tornado asynchronous request non-blocking-Yihe Hall

Source: Internet
Author: User

Objective

Perhaps a classmate is puzzled: Tornado not advertised asynchronous non-blocking solve 10K problem? But I found not torando bad, but you use the wrong. For example, recently found a thing: a Web site open page is slow, the server cpu/memory is OK. The network is also in good condition. Later found that the open page would have a lot of requests for back-end database access, and there is a MongoDB database service API for rest services. But its tornado is wrong, step-by-step to study the problem:

Description

The following examples have 2 URLs, one is a time-consuming request, one is a request that can or should be returned immediately, I think even if a person is not familiar with the technology, from the point of view of the user, he hopes that his visit will not affect the request and will not be affected by other people's request

#!/bin/env python

Import Tornado.httpserver

Import Tornado.ioloop

Import Tornado.options

Import Tornado.web

Import Tornado.httpclient

Import time

From tornado.options import define, Options

Define ("Port", default=8000, help= "run on the given port", Type=int)

Class Sleephandler (Tornado.web.RequestHandler):

def get (self):

Time.sleep (5)

Self.write ("When I Sleep 5s")

Class Justnowhandler (Tornado.web.RequestHandler):

def get (self):

Self.write ("I hope just now")

if __name__ = = "__main__":

Tornado.options.parse_command_line ()

App = Tornado.web.Application (handlers=[

(r "/sleep", Sleephandler), (R "/justnow", Justnowhandler)])

Http_server = Tornado.httpserver.HTTPServer (APP)

Http_server.listen (Options.port)

Tornado.ioloop.IOLoop.instance (). Start ()

If you use a page request or use a tool such as Httpie,curl to access Http://localhost:8000/sleep first, then visit Http://localhost:8000/justnow. You will find that you can return immediately. The Jsutnow request will be blocked until the/sleep request is finished before returning.

Why is this? Why is my request blocked by a/sleep request? If our web requests are usually fast enough we may not be aware of this problem, but in fact there are often time-consuming processes that mean that the application is effectively locked until the processing is complete.

Is it time you remembered @tornado.web.asynchronous this decorator? But the premise of using this decorator is that you need to take time to execute asynchronously, such as the above time.sleep, you just add the adorner is not functional, and it is important to note that tornado by default when the function processing returns, the client's connection is closed. But when you use the @tornado.web.asynchonous adorner, Tornado never close the connection yourself, and you need an explicit self.finish () to close

Most of our functions are blocked, such as the above Time.sleep actually tornado an asynchronous implementation:

#!/bin/env python

Import Tornado.httpserver

Import Tornado.ioloop

Import Tornado.options

Import Tornado.web

Import Tornado.gen

Import Tornado.httpclient

Import Tornado.concurrent

Import Tornado.ioloop

Import time

From tornado.options import define, Options

Define ("Port", default=8000, help= "run on the given port", Type=int)

Class Sleephandler (Tornado.web.RequestHandler):

@tornado. web.asynchronous

@tornado. Gen.coroutine

def get (self):

Yield Tornado.gen.Task (Tornado.ioloop.IOLoop.instance (). Add_timeout, Time.time () + 5)

Self.write ("When I Sleep 5s")

Class Justnowhandler (Tornado.web.RequestHandler):

def get (self):

Self.write ("I hope just now")

if __name__ = = "__main__":

Tornado.options.parse_command_line ()

App = Tornado.web.Application (handlers=[

(r "/sleep", Sleephandler), (R "/justnow", Justnowhandler)])

Http_server = Tornado.httpserver.HTTPServer (APP)

Http_server.listen (Options.port)

Tornado.ioloop.IOLoop.instance (). Start ()

Here's a new tornado.gen.coroutine decorator, and Coroutine is the decorator that was added after 3.0. The previous approach was to use a callback, or see my example:

Class Sleephandler (Tornado.web.RequestHandler):

@tornado. web.asynchronous

def get (self):

Tornado.ioloop.IOLoop.instance (). Add_timeout (Time.time () + 5, Callback=self.on_response)

def on_response (self):

Self.write ("When I Sleep 5s")

Self.finish ()

Callback is used, but the new adorner allows us to achieve the same effect with yield: After you open/sleep and then click/justnow, Justnow requests are immediately returned unaffected. But with the asynchronous decorator, your time-consuming function also needs to perform asynchronous

What you just said is meaningless examples, the following is a bit of a use: Read the MongoDB database data, and then the front-end press the line to write out

#!/bin/env python

Import Tornado.httpserver

Import Tornado.ioloop

Import Tornado.options

Import Tornado.web

Import Tornado.gen

Import Tornado.httpclient

Import Tornado.concurrent

Import Tornado.ioloop

Import time

# a MongoDB-produced Python driver that supports asynchronous databases

Import Motor

From tornado.options import define, Options

Define ("Port", default=8000, help= "run on the given port", Type=int)

# DB is actually a cursor in the test database

db = motor. Motorclient (). Open_sync (). Test

Class Sleephandler (Basehandler):

@tornado. web.asynchronous

@tornado. Gen.coroutine

def get (self):

# It takes time for this line to execute or block, my TT collection has some data and no index

cursor = Db.tt.find (). Sort ([(' A ',-1)])

# This part asynchronously non-blocking execution two does not affect other page requests

while (yield Cursor.fetch_next):

message = Cursor.next_object ()

Self.write (' <li>%s</li> '% message[' a ')

Self.write (' </ul> ')

Self.finish ()

def _on_response (self, message, error):

If error:

Raise Tornado.web.HTTPError ($, error)

Elif message:

For i in message:

Self.write (' <li>%s</li> '% i[' a ')

Else

Self.write (' </ul> ')

Self.finish ()

Class Justnowhandler (Basehandler):

def get (self):

Self.write ("I hope just now")

if __name__ = = "__main__":

Tornado.options.parse_command_line ()

App = Tornado.web.Application (handlers=[

(r "/sleep", Sleephandler), (R "/justnow", Justnowhandler)])

Http_server = Tornado.httpserver.HTTPServer (APP)

Http_server.listen (Options.port)

Tornado.ioloop.IOLoop.instance (). Start ()

A colleague suggests why this time-consuming thing cannot be asynchronously dropped to a tool to execute without blocking my request? Well, I also thought: celery, just GitHub has this thing: tornado-celery

Execute the following program first you want to install RABBITMQ and celery:

#!/bin/env python

Import Tornado.httpserver

Import Tornado.ioloop

Import Tornado.options

Import Tornado.web

Import Tornado.gen

Import Tornado.httpclient

Import Tcelery, Tasks

Import time

From tornado.options import define, Options

Define ("Port", default=8000, help= "run on the given port", Type=int)

Tcelery.setup_nonblocking_producer ()

Class Sleephandler (Tornado.web.RequestHandler):

@tornado. web.asynchronous

@tornado. Gen.coroutine

def get (self):

# The parameters of the Tornado.gen.Task are: the function to be executed, the parameter

Yield Tornado.gen.Task (Tasks.sleep.apply_async, args=[5])

Self.write ("When I Sleep 5s")

Self.finish ()

Class Justnowhandler (Tornado.web.RequestHandler):

def get (self):

Self.write ("I hope just now")

if __name__ = = "__main__":

Tornado.options.parse_command_line ()

App = Tornado.web.Application (handlers=[

(r "/sleep", Sleephandler), (R "/justnow", Justnowhandler)])

Http_server = Tornado.httpserver.HTTPServer (APP)

Http_server.listen (Options.port)

Tornado.ioloop.IOLoop.instance (). Start ()

The task is a celery-defined file that contains the functions we call time.sleep.

Import time

From celery import celery

celery = celery ("Tasks", broker= "Amqp://guest:[email protected]:5672")

Celery.conf.CELERY_RESULT_BACKEND = "AMQP"

@celery. Task

def sleep (seconds):

Time.sleep (float (seconds))

return seconds

if __name__ = = "__main__":

Celery.start ()

Then start the Celelry worker (or else how do you do it?) must have a consumer to take away):

Celery-a Tasks worker--loglevel=info

But the problem here can also be serious: our asynchronous non-blocking relies on celery, or the length of the queue, and if the task is a lot then it needs to wait and be inefficient. Is there a way to make my sync blocking function asynchronous (or tornado to understand and recognize it)?

#!/bin/env python

Import Tornado.httpserver

Import Tornado.ioloop

Import Tornado.options

Import Tornado.web

Import Tornado.httpclient

Import Tornado.gen

From tornado.concurrent import Run_on_executor

# This concurrent library in Python3 comes with python2 need to install sudo pip install futures

From concurrent.futures import Threadpoolexecutor

Import time

From tornado.options import define, Options

Define ("Port", default=8000, help= "run on the given port", Type=int)

Class Sleephandler (Tornado.web.RequestHandler):

Executor = Threadpoolexecutor (2)

#executor is that local variables are not global

@tornado. web.asynchronous

@tornado. Gen.coroutine

def get (self):

# If you execute the asynchronous return value will be called again (just for demonstration), otherwise direct yield is OK

res = yield Self.sleep ()

Self.write ("When I sleep%s S"% res)

Self.finish ()

@run_on_executor

def sleep (self):

Time.sleep (5)

Return 5

Class Justnowhandler (Tornado.web.RequestHandler):

def get (self):

Self.write ("I hope just now")

if __name__ = = "__main__":

Tornado.options.parse_command_line ()

App = Tornado.web.Application (handlers=[

(r "/sleep", Sleephandler), (R "/justnow", Justnowhandler)])

Http_server = Tornado.httpserver.HTTPServer (APP)

Http_server.listen (Options.port)

Tornado.ioloop.IOLoop.instance (). Start ()

Http://www.qytang.com/cn/list/28/434.htm
Http://www.qytang.com/cn/list/28/433.htm
Http://www.qytang.com/cn/list/28/431.htm
Http://www.qytang.com/cn/list/28/328.htm
Http://www.qytang.com/cn/list/28/326.htm
Http://www.qytang.com/cn/list/28/429.htm
Http://www.qytang.com/cn/list/28/428.htm
Http://www.qytang.com/cn/list/28/426.htm
Http://www.qytang.com/cn/list/28/425.htm
Http://www.qytang.com/cn/list/28/424.htm
Http://www.qytang.com/cn/list/28/423.htm

Tornado asynchronous request non-blocking-Yihe Hall

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.