最近迷上了gevent所以研究很多gevent相关的东西。
但是我现在不想写相关gevent和greenlet的东西。因为这一块内容实在太多太大太杂,我自己也还没有完全弄明白,所以等我完全搞清楚测试也测试过了之后。我会写一篇比较系统一点的东西来把我最近研究,和测试过的东西都展现出来。
今天先写一个基于gevent开发的requests库,grequests的使用。
为什么会有地方使用到grequests呢?
首先是对io密集型的需求处理。首先我们都知道,如我们去请求一个网站上的数据,正常来说我们会一条一条的跑,例如这样。
import requests url = ‘http://www.baidu.com‘ x = request.get(url) print x
如果是多个网站的请求 我们可能会使用一个循环以此遍历list url对象。
但是这样就会造一个常见的性能问题。例如中间有一个请求卡住了,或者一些情况导致一个请求长时间没有返回,由于我们的同步请求模式,在得到返回之前我们可能会长时间处于一个io阻塞的状态。这样显而易见,如果有100个请求,不管是性能还是效率肯定都是慢得没得说的。
于是我们才会想要用一种并行的思路去解决类似的问题。如果我们同时开启100个请求,那么最差的情况也就等最后返回的那个家伙返回就可以结束所有的请求了。性能提升是n倍,几乎越多请求异步操作的优势也就越明显。所以今天介绍的grequests库就可以在python里使用gevent基于coroutines(协程)解决这个问题。
这里演示使用代码,异常简单就可以使你的请求性能提升数倍。
import grequests import requests import cProfile urls = [ ‘http://www.xiachufang.com/downloads/baidu_pip/2016030101.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030102.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030103.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030104.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030105.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030106.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030107.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030108.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030109.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030110.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030111.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030112.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030113.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030114.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030115.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030116.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030117.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030118.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030119.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030120.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030121.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030122.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030123.json‘, ‘http://www.xiachufang.com/downloads/baidu_pip/2016030200.json‘, ] def haha(urls): rs = (grequests.get(u) for u in urls) return grequests.map(rs) cProfile.run("haha(urls)") def hehe(urls): hehe = [requests.get(i) for i in urls] return hehe cProfile.run("hehe(urls)")
下面贴出请求所用时间数据 仅供参考。
使用异步在24个请求的平均耗时测试10次计算 平均花费130毫秒
2/1 0.000 0.000 0.132 0.132 coventry.py:651(haha)
在使用同步普通的request库请求的情况下 同样测试10次 平均花费900毫秒 如果中途遇到有单个链接不稳或者超时甚至会花费1秒
2/1 0.000 0.000 1.149 1.149 coventry.py:657(hehe)
总结:
在io密集,等待io时间长的请求量级越大的情况,这样的性能提升越是明显,使用并发或者协程至少提升性能5倍以上我们越是应该使用异步或并行操作来减少io的等待时间。python比较有效和高效的处理方案我觉得非coroutines(协程)莫属了,而相关库最好用的又是gevent,所以非常值得深入研究下去,一探究竟。使用类似操作减少io等待,提升整个业务性能。