tornado 异步非阻塞

1、同步阻塞

   A、socket例子

import socket
def handle_request(client):
buf = client.recv(1024)
client.send(b"HTTP/1.1 200 OK ")
client.send(b"Hello, Seven")

def main():
print('main()')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8083))
sock.listen(5)
while True:
connection, address = sock.accept()
handle_request(connection)
connection.close()

if __name__ == '__main__':
main()

例子A为socket监听浏览器行为的过程并且返回浏览器访问数据

B、tornado同步阻塞例子
import tornado.ioloop
import tornado.web
import requests
class MainHandler(tornado.web.RequestHandler):
def get(self):
requests.get('http://www.google.com/')

class LoginHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")

application = tornado.web.Application([
(r"/index", MainHandler),
(r"/login", LoginHandler),
])

if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
例子B为tornado同步阻塞的例子:如果访问index页面,http://www.google.com/如果被阻塞,此时访问/login,服务器也无法处理/login的请求行为,/login因为/index阻塞而被阻塞;

上述原因:

  1、浏览器其实就是一个socket客户端,而web应用其实就是一个socket服务端,并且web应用在服务器上一直在监听某个端口。

  2、当浏览器请求某个web应用时,需要指定服务器的IP(DNS解析)和端口建立一个socket连接。

  3、建立链接后,web应用根据请求的不同,给用户返回相应的数据。

  4、断开socket连接。(之所以说http是短链接,其实就是因为每次请求完成后,服务器就会断开socket链接)

  对于Web框架来说,一般分为两类,其中一类则是包含上述 4部分 内容的框架,另外一类就是只包含 第3部分 功能的框架。tornado就是一中属于前者的框架。tornado 是一个基于 Python 开发的web框架,较其他 Web 框架的区别是:采用了非阻塞的方式和对epoll的应用。这意味着对于实时 Web 服务来说,Tornado 是一个理想的 Web 框架。

 

2、解决同步阻塞

A、装饰器 + Future 从而实现Tornado的异步非阻塞

import tornado.ioloop
import tornado.web
from tornado.web import asynchronous
from tornado import gen #tornado中的协程模块:tornado.gen:
from concurrent.futures import Future
import time
class AsyncHandler(tornado.web.RequestHandler):
'''
Future实现非阻塞
'''
@gen.coroutine
def get(self):
future = Future()
tornado.ioloop.IOLoop.current().add_timeout(time.time() + 10, self.doing)
future.add_done_callback(self.doing)
yield future
# 或
# tornado.ioloop.IOLoop.current().add_future(future,self.doing)
# yield future

def doing(self, *args, **kwargs):
self.write('async')
self.finish()

class LoginHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")

application = tornado.web.Application([
(r"/index", AsyncHandler),
(r"/login", LoginHandler),
])

if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
如果访问index页面,AsyncHandler中需要等待,被阻塞,此时访问/login,服务器也可以处理/login的请求行为,/login不会因为/index阻塞而被阻塞;

B、Tornado提供了httpclient类库用于发送Http请求,装饰器 + httpclient配合Tornado的异步非阻塞使用。

import tornado.ioloop
import tornado.web
from tornado import httpclient
from tornado.web import asynchronous
from tornado import gen #tornado中的协程模块:tornado.gen:

class MainHandler(tornado.web.RequestHandler):
'''
httpclient 方式实现非阻塞
'''
@asynchronous
@gen.coroutine
def get(self):
print
'start get '
http = httpclient.AsyncHTTPClient()
http.fetch("http://www.google.com/", self.callback)
self.write('end')

def callback(self, response):
print(response.body)

class LoginHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")

application = tornado.web.Application([
(r"/index", MainHandler),
(r"/login", LoginHandler),
])

if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
如果访问index页面,AsyncHandler中需要等待,被阻塞,此时访问/login,服务器也可以处理/login的请求行为,/login不会因为/index阻塞而被阻塞;
原文地址:https://www.cnblogs.com/yoyo008/p/9305975.html