异步非阻塞

阻塞式:(适用于所有框架,Django,Flask,Tornado,Bottle)
  一个请求到来未处理完成,后续一直等待
  解决方案:多线程,多进程

异步非阻塞(存在IO请求): Tornado(单进程+单线程)
  使用异步非阻塞,需要遵循Tornado框架内部规则,gen

  多个连接请求,连接给服务端,如果是有异步非阻塞的话,服务端会接收所有的请求交由后台处理,等待其他链接的同时,原先连接不断开,直至返回后台处理完成的结果!
  外部请求,连接服务端 或在select中创建Future对象,然后服务端再把请求交给业务处理平台,此时select监听的列表中又会生成一个socket对象,当业务平台对请求处理完成之后就会把信息返回到服务端的select监听列表中,同时对这个Future对象赋值,用于标记服务端是否要给客户端返回请求信息。

  执行流程,本质上都是返回一个future对象,如果对这个对象被set_result了就返回值,否则就是夯住,一直保持连接,不终止请求。

1、基本使用

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

class AsyncHandler(tornado.web.RequestHandler):

    @gen.coroutine
def get(self):
future = Future()
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()

  当发送GET请求时,由于方法被@gen.coroutine装饰且yield 一个 Future对象,那么Tornado会等待,等待用户向future对象中放置数据或者发送信号,如果获取到数据或信号之后,就开始执行doing方法。

  异步非阻塞体现在当在Tornaod等待用户向future对象中放置数据时,还可以处理其他请求。

  注意:在等待用户向future对象中放置数据或信号时,此连接是不断开的。

2、同步阻塞和异步非阻塞对比

class SyncHandler(tornado.web.RequestHandler):

    def get(self):
self.doing()
self.write('sync') def doing(self):
time.sleep(10)

同步阻塞

class AsyncHandler(tornado.web.RequestHandler):
@gen.coroutine
def get(self):
future = Future()
tornado.ioloop.IOLoop.current().add_timeout(time.time() + 5, self.doing)
yield future def doing(self, *args, **kwargs):
self.write('async')
self.finish()

异步非阻塞

3、httpclient类库

  Tornado提供了httpclient类库用于发送Http请求,其配合Tornado的异步非阻塞使用。

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.web
from tornado import gen
from tornado import httpclient # 方式一:
class AsyncHandler(tornado.web.RequestHandler):
@gen.coroutine
def get(self, *args, **kwargs):
print('进入')
http = httpclient.AsyncHTTPClient()
data = yield http.fetch("http://www.google.com")
print('完事',data)
self.finish('6666') # 方式二:
# class AsyncHandler(tornado.web.RequestHandler):
# @gen.coroutine
# def get(self):
# print('进入')
# http = httpclient.AsyncHTTPClient()
# yield http.fetch("http://www.google.com", self.done)
#
# def done(self, response):
# print('完事')
# self.finish('666') application = tornado.web.Application([
(r"/async", AsyncHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
需要先安装支持异步操作Mysql的类库:
Tornado-MySQL: https://github.com/PyMySQL/Tornado-MySQL#installation pip3 install Tornado-MySQL """ import tornado.web
from tornado import gen import tornado_mysql
from tornado_mysql import pools POOL = pools.Pool(
dict(host='127.0.0.1', port=3306, user='root', passwd='', db='cmdb'),
max_idle_connections=1,
max_recycle_sec=3) @gen.coroutine
def get_user_by_conn_pool(user):
cur = yield POOL.execute("SELECT SLEEP(%s)", (user,))
row = cur.fetchone()
raise gen.Return(row) @gen.coroutine
def get_user(user):
conn = yield tornado_mysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='cmdb',
charset='utf8')
cur = conn.cursor()
# yield cur.execute("SELECT name,email FROM web_models_userprofile where name=%s", (user,))
yield cur.execute("select sleep(10)")
row = cur.fetchone()
cur.close()
conn.close()
raise gen.Return(row) class LoginHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.render('login.html') @gen.coroutine
def post(self, *args, **kwargs):
user = self.get_argument('user')
data = yield gen.Task(get_user, user)
if data:
print(data)
self.redirect('http://www.oldboyedu.com')
else:
self.render('login.html') application = tornado.web.Application([
(r"/login", LoginHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

基于异步非阻塞和Tornado-MySQL实现用户登录示例

异步非阻塞渐进学习代码+笔记注释

import tornado.ioloop
import tornado.web
from tornado.web import RequestHandler
from tornado.httpserver import HTTPServer # 单线程操作,请求来排队等待,顺序执行
#人为干预模拟IO设置 sleep10秒
class IndexHandler(RequestHandler):
def get(self):
print('开始')
import time
time.sleep(10)
self.write("Hello, world")
print('结束') application = tornado.web.Application([
(r"/index", IndexHandler),
]) if __name__ == "__main__":
# 单进程单线程
application.listen(8888)
tornado.ioloop.IOLoop.instance().start() # 利用多进程 实现
# server = HTTPServer(application)
# server.bind(8888)
# server.start(4) # Forks multiple sub-processes
# tornado.ioloop.IOLoop.current().start()

s1.py

import tornado.ioloop
import tornado.web
from tornado.web import RequestHandler
from tornado import gen # 执行异步IO 导入gen模块
from tornado.concurrent import Future # 执行异步IO导入 Future模块,引用Future对象
import time # 单线程 实现异步非阻塞操作!所有的连接请求不等待直接执行
class IndexHandler(RequestHandler):
@gen.coroutine # 异步IO 固定写法,在请求上以装饰器的形式添加
def get(self):
print('开始')
future = Future() #创建 Future() 对象
tornado.ioloop.IOLoop.current().add_timeout(time.time() + 10, self.doing) #给当前的客户端添加超时时间,固定写法
yield future # yield 返回 Future() 对象 IO操作的固定写法 # 操作完成之后,需要执行的回调函数,一般是用于给请求返回消息
def doing(self, *args, **kwargs):
self.write('async') # 返回消息
self.finish() #结束连接 application = tornado.web.Application([
(r"/index", IndexHandler),
]) if __name__ == "__main__":
# 单线程
application.listen(8888)
tornado.ioloop.IOLoop.instance().start() # 多进程
# server = HTTPServer(application)
# server.bind(8888)
# server.start(4) # Forks multiple sub-processes
# tornado.ioloop.IOLoop.current().start()

s2.py

import tornado.ioloop
import tornado.web
from tornado.web import RequestHandler
from tornado import gen
from tornado.concurrent import Future
import time
from tornado import httpclient #针对HTTP请求进行异步非阻塞处理的模块 # 针对API接口 HTTP请求 实现异步非阻塞
class IndexHandler(RequestHandler):
@gen.coroutine
def get(self):
print('收到订单')
http = httpclient.AsyncHTTPClient() #创建 执行异步非阻塞 客户端
yield http.fetch("http://www.github.com", self.done) # 固定写法 请求对某个API接口(url地址)传递消息,处理完毕执行回调函数 #请求处理完毕,执行的回调函数。
def done(self, response):
self.write('订单成功') # 给请求返回的信息
self.finish() # 断开连接 application = tornado.web.Application([
(r"/index", IndexHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start() # server = HTTPServer(application)
# server.bind(8888)
# server.start(4) # Forks multiple sub-processes
# tornado.ioloop.IOLoop.current().start()

s3.py

import tornado.ioloop
import tornado.web
from tornado.web import RequestHandler
from tornado import gen
from tornado.concurrent import Future
import time
from tornado import httpclient fu = None
class IndexHandler(RequestHandler):
@gen.coroutine
def get(self):
global fu
print('疯狂的追求')
fu = Future() # 创建Future对象,建立连接,如果没有人改变状态,请求就会永久存在连接不断开,除非Future() 对象被赋值或是反生改变
# fu.set_result("") # 给Future 对象赋值,fu发生变化,返回请求。
fu.add_done_callback(self.done)# 给fu添加要执行的回调函数
yield fu def done(self, response):
self.write('终于等到你')
self.finish() class TestHandler(RequestHandler):
def get(self):
fu.set_result(666) # 给future对象赋值,用以改变连接状态,返回消息 (注意:返回的内容就是 result的值)
self.write('我只能帮你到这里了') application = tornado.web.Application([
(r"/index", IndexHandler),
(r"/test", TestHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

s4.py

import tornado.ioloop
import tornado.web
from tornado.web import RequestHandler
from tornado import gen
from tornado.concurrent import Future
import time
from tornado import httpclient
from threading import Thread def waiting(futher):
#线程要执行处理的函数
import time
time.sleep(10)
futher.set_result(666) class IndexHandler(RequestHandler):
@gen.coroutine
def get(self):
global fu
print('疯狂的追求')
fu = Future()
fu.add_done_callback(self.done) thread = Thread(target=waiting,args=(fu,)) # 开一个线程 自动给设置值,以自动给请求返回处理的消息
thread.start() yield fu def done(self, response):
self.write('终于等到你')
self.finish() application = tornado.web.Application([
(r"/index", IndexHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

s5.py

import tornado.web
import tornado.ioloop
from tornado import gen
import tornado_mysql @gen.coroutine # 注意需要写上装饰器
def get_user(user):
# 异步非阻塞,Task操作的函数,连接数据库,注意语法结构
conn = yield tornado_mysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tornadoTest',
charset='utf8')
cur = conn.cursor()
# yield cur.execute("SELECT name,email FROM web_models_userprofile where name=%s", (user,))
yield cur.execute("select sleep(10)")
row = cur.fetchone()
cur.close()
conn.close()
raise gen.Return(row) # 注意task函数的返回值 class LoginHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.render('login.html') @gen.coroutine
def post(self, *args, **kwargs):
user = self.get_argument('user')
data = yield gen.Task(get_user, user) # 执行Task函数,内部还是返回future对象。Task函数上第一个参数是要执行的函数,第二个是参数
if data:
print(data)
self.redirect('http://www.baidu.com')
else:
self.render('login.html') #原始方案,请求来了,连接数据库,等待操作完成,关闭连接!
# def post(self, *args, **kwargs):
# user = self.get_argument('user')
# # 连接数据库: IO耗时
# # 查询语句: IO耗时
# # 获取结果
# data = {'id':1,'user':'alex'}
# if data:
# print(data)
# self.redirect('http://www.baidu.com')
# else:
# self.render('login.html') application = tornado.web.Application([
(r"/login", LoginHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

s6.py

web框架之Tornado

Python web框架 Tornado(二)异步非阻塞的更多相关文章

  1. Python Web框架Tornado的异步处理代码演示样例

    1. What is Tornado Tornado是一个轻量级但高性能的Python web框架,与还有一个流行的Python web框架Django相比.tornado不提供操作数据库的ORM接口 ...

  2. Python web框架 Tornado异步非阻塞

    Python web框架 Tornado异步非阻塞   异步非阻塞 阻塞式:(适用于所有框架,Django,Flask,Tornado,Bottle) 一个请求到来未处理完成,后续一直等待 解决方案: ...

  3. Python Web框架 tornado 异步原理

    Python Web框架 tornado 异步原理 参考:http://www.jb51.net/article/64747.htm 待整理

  4. Tornado的异步非阻塞

    阻塞和非阻塞Web框架 只有Tornado和Node.js是异步非阻塞的,其他所有的web框架都是阻塞式的. Tornado阻塞和非阻塞两种模式都支持. 阻塞式: 代表:Django.Flask.To ...

  5. tornado 之 异步非阻塞

    异步非阻塞 1.基本使用 装饰器 + Future 从而实现Tornado的异步非阻塞 import tornado.web import tornado.ioloop from tornado im ...

  6. Tornado之异步非阻塞

    同步模式:同步模式下,只有处理完前一个任务下一个才会执行 class MainHandler(tornado.web.RequestHandler): def get(self): time.slee ...

  7. 异步非阻塞IO的Python Web框架--Tornado

    Tornado的全称是Torado Web Server,从名字上就可知它可用作Web服务器,但同时它也是一个Python Web的开发框架.最初是在FriendFeed公司的网站上使用,FaceBo ...

  8. Python web框架——Tornado

    Tornado是一个Python Web框架和异步网络库,最初由FriendFeed开发.通过使用非阻塞网络I / O,Tornado可以扩展到数万个开放连接,使其成为需要长时间连接每个用户的长轮询, ...

  9. 关于Python Web框架——Tornado

    关于Tornado的入门看这篇文章,写的非常好: https://zhuanlan.zhihu.com/p/37382503 Tornado 是一个Python web框架和异步网络库,使用非阻塞网络 ...

随机推荐

  1. yii2:如果获取config/web.php配置的值?

    return [ 'version' => '1.0.1', 'category-map' => [ 1 => '样式1', 2 => '样式2', 3 => '样式3' ...

  2. MapReduce程序——WordCount(Windows_Eclipse + Ubuntu14.04_Hadoop2.9.0)

    本文主要参考<Hadoop应用开发技术详解(作者:刘刚)> 一.工作环境 Windows7: Eclipse + JDK1.8.0 Ubuntu14.04:Hadoop2.9.0 二.准备 ...

  3. request方法传入动态参数的一个"误区"

    晚上写了一个请求类,传了一个动态参数进去,实例化测试的时候,发现请求数据根本没法读到,先附上代码 import requests class MyRequests: def send_request( ...

  4. Kestrel 服务器部署多站点问题 (nginx 反向代理)

    Kestrel 作为微软的跨平台 web 服务器,有些地方用的好不是很熟. 作为一款嵌套到 dll 中的进程级 web 服务器,在同一台服务器上部署多站点确实还存在一点问题. 今天采用 nginx 做 ...

  5. C++空类和string类

    1. 空类 1.1 空类默认哪六个成员函数. class Empty { public: Empty(); //缺省构造函数 Empty e; Empty( const Empty& ); / ...

  6. python面向对象编程 继承 组合 接口和抽象类

    1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均用点来访问自己的 ...

  7. MVC框架中的值提供机制(一)

    在MVC框架中action方法中的Model数据的绑定的来源有很多个,可能是http请求中的get参数或是post提交的表单数据,会是json字符串或是路径中的相关数据;MVC框架中针对这些不同的数据 ...

  8. org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource

    二月 20, 2017 3:09:47 下午 org.apache.catalina.startup.SetAllPropertiesRule begin警告: [SetAllPropertiesRu ...

  9. Android系统自带分享功能的实现(可同时分享文字和图片)

     /** * 分享功能 * * @param context * 上下文 * @param activityTitle * Activity的名字 * @param msgTitle * 消息标题 ...

  10. (效果三)js实现选项卡切换

    开发了很久的小程序,在接到一个h5移动端页面的时候,很多原生的东西都忘了,虽然说我们随着工作经验的增加,处理业务逻辑的能力在提高,但是基础的东西如果长时间不用,也会逐渐忘记.所以以后会经常总结原生的一 ...