1. What is Tornado

Tornado是一个轻量级但高性能的Python web框架,与还有一个流行的Python web框架Django相比。tornado不提供操作数据库的ORM接口及严格的MVC开发模式,但能够提供主要的web server功能。故它是轻量级的;它借助non-blocking and event-driven的I/O模型(epoll或kqueue)实现了一套异步网络库,故它是高性能的。

Tornado的轻量级+高性能特性使得它特别适用于提供web api的场合,使用合理的话,其非堵塞+异步能力能够应对C10K问题。

须要特别注意的是,因为Python的GIL导致多线程总是单核运行的”特点”,tornado处理http请求时,若某个请求的后端响应有堵塞现象(如从DB或磁盘读数据导致处理时间非常长),则会导致其他http请求也被block,这会严重拖累tornado在高并发场景下的性能。

幸运的是。tornado提供了异步处理请求的能力,在异步模式下,我们能够通过传入回调函数或借助tornado提供的tornado.gen.coroutine装饰器,使得tornado内部的io loop在等待当前请求响应结果的同一时候,仍然能够接受其他的http请求,这样就避免了某个耗时操作影响tornado的处理能力。

2. 怎样在tornado框架下编写异步处理代码

Tornado官网文档给出了几个简单的异步代码演示样例,只是说实话,代码太过简单(都是在某个uri的handler类的get或post函数中展现了主要的异步语法),没有多大的实战意义。

在实际项目中。复杂的处理逻辑不可能都堆在get或post函数中,而是会封装在其他class中供handler类的get或post函数调用。

所以,本文给出一个稍复杂的实例,旨在说明怎样在其他class的函数中实现异步处理逻辑,以实现http请求异步化处理的目的。

如果如今的需求是用tornado实现一个web server,支持名为cityhotel的uri方法,当client通过http GET请求訪问该uri时,web server依据query參数指定的城市,去请求存放hotel具体数据的还有一个后端api。进行业务处理后返回某个连锁hotel在该城市的全部门店给client。

如果client GET请求的url格式为:http://host/api/hotel/cityhotel?city=xxx
再如果存放hotel具体数据的后端api接口为:http://hotel_backend/getCityHotels?

city=xxx

依据上面的场景,因为我们用tornado实现的web server接到client的请求后,还要去还有一个API接口请求基础数据,而后者在返回前,tornado会block,所以,这样的场景下,tornado最好以异步方式请求那个提供基础数据的API。避免不可控的后端拖累tornado的响应性能。

依据上面描写叙述的业务需求。以下的代码示范了怎样通过异步方式处理业务处理。

模块入口文件(main.py):

#!/bin/env pythonimport tornado.ioloop
import tornado.web
import tornado.gen
import hotelcoreclass CityHotelHandler(tornado.web.RequestHandler):@tornado.gen.coroutinedef get(self):## parse query paramsparams = {}keys = ['city']for key in keys:value = self.get_query_argument(key)params[key] = value(status, rsp) = yield hotelcore.HotelApiHandler.get_city_hotel(params['city'])if 200 == status:self.set_header('content-type', 'application/json')self.finish(rsp)else:self.set_status(404)self.finish()def main():app_inst = tornado.web.Application([(r'/api/hotel/cityhotel', CityHotelHandler),], compress_response = True)app_inst.listen(8218)tornado.ioloop.IOLoop.current().start()if '__main__' == __name__:main()

处理业务逻辑的module封装在hotelcore.py文件里,代码例如以下:

#!/bin/env python
#-*- encoding: utf-8 -*-import jsonfrom tornado import gen
from tornado import httpclientclass HotelApiHandler(object):_cfg_dict = {'api_host' : 'api.hotelbackend.com',}@classmethod@gen.coroutinedef get_city_hotel(cls, city):ret = yield cls._parallel_fetch_city_hotel(city)raise gen.Return((200, ret))@classmethod@gen.coroutinedef _parallel_fetch_city_hotel(cls, city):base_url = 'http://%s/v1/getCityHotel' % (cls._cfg_dict['api_host'])## hote type: 1=normal room; 2=deluxe roomhotel_type = {'normal': 1, 'deluxe': 2}urls = []for v in hotel_type.values():api_url = '%s?city=%s&level=%s' % (base_url, city, v)urls.append(api_url)## issue async http requesthttp_clt = httpclient.AsyncHTTPClient()rsps_dict = yield dict(normal_room = http_clt.fetch(urls[0]), deluxe_room = http_clt.fetch(urls[1]))city_hotel_info = cls._parse_city_hotel(rsps_dict, city)ret = { }if len(city_hotel_info):ret['errno']  = 0ret['errmsg'] = 'SUCCESS'ret['data']   = city_hotel_infoelse:ret['errno']  = 1ret['errmsg'] = 'Service Not Found at This City'ret['data']   = ''raise gen.Return(ret)@classmethoddef _parse_city_hotel(cls, rsp_dict, city):city_hotel_info = {}for hotel_level, rsp in rsp_dict.items():rsp_json = json.loads(rsp.body)datas = rsp_json['data']for city_id, city_detail in datas.items():name = city_detail['name']if city in name:city_hotel_info[hotel_level] = city_detailbreakreturn city_hotel_info

对以上代码的几点补充说明:

  • 编写tornado异步处理代码须要对Python的decorator语法和generator/yield语法比較熟悉
  • tornado提供的装饰器@gen.coroutine表明被装饰函数是个异步处理函数,该函数的调用不会block tornado主线程
  • 被@gen.coroutine装饰的函数中,须要异步运行的耗时函数用yield来调用,yield本身返回的是个generator,结合@gen.coroutine后。它返回一个tornado定义的Future类型的对象
  • yield调用的函数在运行过程中。进程控制权会返给主线程,故即使该函数须要较长运行时间,tornado的主线程也能够继续处理其他请求
  • 在Python 2.x版本号的语法中。generator中不同意用return返回函数的返回值。必须用tornado提供的raise gen.Return(ret)达到返回的目的。这是个比較tricky的方法
  • yield返回的Future对象能够通过调用body属性来获取通过yield调用的函数的返回值
  • 仅仅要结合上述几点理解了@gen.coroutine和yield在tornado异步编程中的语法意义,那么,写出复杂的异步调用代码与编写实现同样功能但tornado总体性能无法保证的同步调用代码相比。实现难度就差点儿不存在了。

上面的代码非常多语法细节没有展开,希望实现思路能帮助到有缘人。^_^

參考资料

  1. Tornado Doc: User’s guide
  2. Book: Introduction to tornado chapter 5. asynchronous web services

转载于:https://www.cnblogs.com/llguanli/p/8406251.html

Python Web框架Tornado的异步处理代码演示样例相关推荐

  1. pythondjangoweb典型模块开发实战 pdf下载_胡阳《Django企业开发实战高效Python Web框架指南》PDF及代码...

    Python社区中的框架Django 的定位是企业级开发框架,全功能 Web开发框架,少代码快速开发 Web应用.从开发速度还是上线后新功能的迭代,Django 都能很好地满足需求. 学完 Pytho ...

  2. Python web框架 Tornado(二)异步非阻塞使用以及原理

    原文: http://www.liangxiansen.cn/2018/04/11/tornado/ 作者: 梁先森 稍有改动 Tornado默认是单进程单线程.实时的web特性通常需要为每个用户一个 ...

  3. Python web框架: Tornado

    1.Tornado 中文文档https://tornado-zh.readthedocs.io/zh/latest/ Tornado:python编写的web服务器兼web应用框架 1.Tornado ...

  4. c语言学习之结构篇代码演示样例-输入n个同学的姓名,数学英语成绩,依照平均分从低到高排序并输出...

    #include<stdio.h> void main(){ const int count = 5;//定义数量 struct student{ char name[80]; float ...

  5. python twisted和flask_浅谈Python Web 框架:Django, Twisted, Tornado, Flask, Cyclone 和 Pyramid...

    Django 是一个高级的 Python Web 框架,支持快速开发,简洁.实用的设计.如果你正在建一个和电子商务网站相似的应用,那你应该选择用 Django 框架.它能使你快速完成工作,也不必担心太 ...

  6. 防掉线、防脱发的异步高性能Python Web框架

    FastAPI是一个用于构建API的现代.快速(高性能)的Web框架,使用Python 3.6+并基于标准的Python类型提示. 可与NodeJS和Go比肩的极高性能(归功于Starlette和Py ...

  7. python web框架介绍对比

    Django Python框架虽然说是百花齐放,但仍然有那么一家是最大的,它就是Django.要说Django是Python框架里最好的,有人同意也有人 坚决反对,但说Django的文档最完善.市场占 ...

  8. python写web难受-(2017)你最不建议使用的Python Web框架?

    原标题:(2017)你最不建议使用的Python Web框架? 前言 这是一篇发在知乎专栏的文章,内容是之前我提的「(2017)你最不建议使用的Python Web框架?」下的回答.不过有些话没有说完 ...

  9. python的web框架哪个最好学_2018年要学习的10大Python Web框架

    通过为开发人员提供应用程序开发结构,框架使开发人员的生活更轻松.他们自动执行通用解决方案,缩短开发时间,并允许开发人员更多地关注应用程序逻辑而不是常规元素. 在本文中,我们分享了我们自己的前十大Pyt ...

最新文章

  1. PandaRSS 自助服务系统安装配置
  2. SpringCloud 应用在 Kubernetes 上的最佳实践 — 高可用(熔断)
  3. 【放置奇兵】魔兽资源总消耗
  4. 出现ORA - 1017用户名/口令无效; 登录被拒绝 的问题
  5. 大二暑假周进度总结03
  6. 锁、C#中Monitor和Lock以及区别
  7. 阿里大数据分析与应用(part6)--数据大屏DataV
  8. 前端学习(1965)vue之电商管理系统电商系统之渲染添加参数的按钮
  9. 一个自动生成关键字索引页面的比处理文件
  10. jar注册成服务器,Spring Boot项目生成jar包,并在windows服务器中注册成服务,开机启动(示例代码)...
  11. pandas手册_Github标星6000+ 这可能是最全的机器学习工具手册
  12. 战地5离线bot模式_战地系列、烂橘子平台下载更新慢咋办?我这里有两个亲测有有效的方式。...
  13. uboot源码分析(1)uboot 命令解析流程简析
  14. 博客开通了-里面有秘密哦
  15. 11.11 开课二个月零七天(ajax和bootstrp做弹窗)
  16. python照片过人脸_python图片人脸检测
  17. 谷歌地图,计算两个坐标点之间的距离
  18. 汽水分离再热器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  19. vue 将echarts的图片导出成pdf文件
  20. python机器学习——加州房价

热门文章

  1. Object.prototype 原型和原型链
  2. CentOS 7 搭建 LAMP
  3. Delphi关于记录文件的操作
  4. SGU traffic light
  5. cocos3.2中如何创建一个场景
  6. 关于学力、同等学力与学历、同等学历的区别
  7. Linux 下杀毒软件 clamav 的安装和使用
  8. 各种机器学习的优缺点及应用场景
  9. 05 MapReduce应用案例01
  10. 与其他.Net异步模式和类型进行互操作