在前面几个博客中咱们一一对应解决了消费者消费的速度跟不上生产者,浪费咱们大量的时间去等待的问题,在这里,针对业务逻辑比较耗时间的问题,咱们还有除了多进程以外更优的解决方式,那就是协程和异步协程。在引入这个概念以前咱们先看 看这个图: html
从这个图片咱们能够看出来,假如来了9个任务,即便咱们开了多进程,在业务的执行过程当中咱们依旧是同步操做,因此执行完这一波任务咱们一共须要9s,虽然比单进程快了3倍,可是在机器条件能够(确定能够)的状况下,咱们如何更加合理的利用给咱们的资源呢?因而异步协程的优点就来了:python
根据这张图咱们能够看出来,在任务1执行完业务逻辑1的时候,任务2就能够开始执行,这样当任务2执行完业务逻辑1的时候,任务3就开始执行了,这样咱们3个进程,总共耗时只须要5s,比上面同步的方式快了足足4s,省去了等待的时间,让模块之间衔接和调用更加充分。编程
在python中,咱们先介绍一下2.0的协程:gevent的使用,在python3.4以后添加了syncoio的使用,这篇博客咱们就专门针对业务逻辑部分进行深度的优化:网络
gevent是第三方库,经过greenlet实现协程,其基本思想是:异步
当一个greenlet遇到IO操做时,好比访问网络,就自动切换到其余的greenlet,等到IO操做完成,再在适当的时候切换回来继续执行。因为IO操做很是耗时,常常使程序处于等待状态,有了gevent为咱们自动切换协程,就保证总有greenlet在运行,而不是等待IO(引用)。async
好比下面代码:oop
from gevent import monkey monkey.patch_all() import gevent import time # TODO 此处是业务逻辑操做 def logicDel(data): time.sleep(2) print('im running',data) if __name__ == '__main__': # 在这里咱们声明几个任务,把任务放到一个list中去作分配调度 tasks=[gevent.spawn(logicDel,data) for data in range(9)] gevent.joinall(tasks)
咱们能够看到咱们在一个tasks里面9个任务,每一个任务执行都要sleep2秒,若是是阻塞式运行就须要18s,可是咱们加入了协程,全部的任务完成只须要2s,其中原理和上图(异步加载图)同样,这里就不赘述了。优化
然而有时候咱们代码业务逻辑中一个业务执行不仅有一个任务,其中每一个任务之间还有调度依赖的关系,这时候咱们的gevent就显得有点力不从心了,这里就引进了python3.4以后的一个自带的包asyncio——异步协程。spa
asyncio的编程模型就是一个消息循环。咱们从asyncio模块中直接获取一个EventLoop
的引用,而后把须要执行的协程扔到EventLoop
中执行,就实现了异步IO。用asyncio
实现Hello world
代码以下:code
import threading import asyncio @asyncio.coroutine def hello(): print('Hello world11111111 (%s)' % threading.currentThread()) yield from asyncio.sleep(1) print('Hello again22222222 (%s)' % threading.currentThread()) loop = asyncio.get_event_loop() tasks = [hello(), hello()] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
其中每一个tasks都是非阻塞式的,固然这个仍是没有解决一个业务有多个任务且每一个任务之间存在依赖关系应当怎么解决的问题,由于咱们尚未引用async await:
import asyncio import time # Borrowed from http://curio.readthedocs.org/en/latest/tutorial.html. # @asyncio.coroutine async def myslep(n): print(n) time.sleep(10) asyncio.sleep(5) async def countdown(number, n): while n > 0: print('T-minus', n, '({})'.format(number)) # await myslep(n) tasks2=[] await asyncio.ensure_future(myslep(n)) # time.sleep(2) n -= 1 loop = asyncio.get_event_loop() tasks = [ asyncio.ensure_future(countdown("A", 2)), asyncio.ensure_future(countdown("B", 3)), asyncio.ensure_future(countdown("C", 3)), ] loop.run_until_complete(asyncio.wait(tasks)) loop.close()