gevent是基于协程的Python网络库。

协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序,当程序中存在大量不需要CPU的操作时(IO),适用于协程。

特点:基于libev的快速事件循环(Linux上epoll,FreeBSD上kqueue),基于greenlet的轻量级执行单元。而且其中有个monkey类,将现有基于Python线程直接转化为greenlet(类似于打patch)。

libev:libev是libevent之后的一个事件驱动的编程框架,其接口和libevent基本类似。据官方介绍,其性能比libevent还要高,bug比libevent还少。Libev通过一个structev_loop结构表示一个事件驱动的框架。在这个框架里面通过ev_xxx结构,ev_init、ev_xxx_set、ev_xxx_start接口向这个事件驱动的框架里面注册事件监控器,当相应的事件监控器的事件出现时,便会触发该事件监控器的处理逻辑,去处理该事件。处理完之后,这些监控器进入到下一轮的监控中。而libevent是一个事件触发的网络库,适用于windows、linux、bsd等多种平台,内部使用select、epoll、kqueue、IOCP等系统调用管理事件机制,libevent支持用户使用三种类型的事件,分别是网络IO、定时器、信号三种,Libev 除了提供了基本的三大类事件(IO事件、定时器事件、信号事件)外还提供了周期事件、子进程事件、文件状态改变事件等多个事件,libevent支持多线程编程,每个事件需要关联到自己的event_base。

greenlet:指的是使用一个任务调度器和一些生成器或者协程实现协作式用户空间多线程的一种伪并发机制,即所谓的微线程。主要思想是:生成器函数或者协程函数中的yield语句挂起函数的执行,直到稍后使用next()或send()操作进行恢复为止。可以使用一个调度器循环在一组生成器函数之间协作多个任务。greenlet不是一种真正的并发机制,而是在同一线程内,在不同函数的执行代码块之间切换,实施“你运行一会、我运行一会”,并且在进行切换时必须指定何时切换以及切换到哪,因此,greenlet本质是一种合理安排了的串行。

monkey patch:在最开头的地方gevent.monkey.patch_all();把标准库中的thread/socket等给替换掉.这样我们在后面使用socket的时候可以跟平常一样使用,无需修改任何代码,如果不进行 monkey patch,会造成严重后果,性能下降,数据错误,代码切换异常等。

要想理解gevent首先要理解gevent的调度流程,gevent中有一个hub的概念,也就是MainThread,用于调度所有其它的greenlet实例。

每次从hub切换到一个greenlet后,都会回到hub,这就是gevent的关键,gevent中并没有greenlet链的说法,所有都是向主循环注册greenlet.switch方法,主循环在合适的时机切换回来。为什么每次都要切换到hub呢?

1.hub是事件驱动的核心,每次切换到hub后将继续循环事件。如果在一个greenlet中不出来,那么其它greenlet将得不到调用。

2.维持两者关系肯定比维持多个关系简单。每次我们所关心的就是hub以及当前greenlet,不需要考虑各个greenlet之间关系。

下面看一个简单的gevent的例子:

我们对这段小代码进行debug,然后在控制台查看线程数:

只有一个线程,他run的其实是greenlet这个伪线程。

然后看执行结果:

我们用显式的sleep使其进行切换,可以看到在sleep后,代码切换到了其他greenlet,因为gevent认为此处出现了阻塞,一旦检测到阻塞,gevent就会自动进行greenlet切换。如果不进行显式调用,则greenlet其实是顺序执行的,因为本质上它是串行的,现在我们将sleep去掉,结果是这样:

实际代码里,我们不会用gevent.sleep()去切换协程,而是在执行到IO操作时,gevent自动切换,代码如下:

我们没有显式的进行sleep,而是依赖各个IO操作自身的阻塞时间,下面我们看下结果:

可以看到,结束顺序和IO发起顺序并不一致。gevent.spawn()方法创建greenlet实例并调用其start方法发起,然后通过gevent.joinall将greenlet实例加入到greenlet执行队列中等待其完成,这里可以为其设置超时时间。

gevent还可以作为起celery worker和celery beat时的POOL(支持prefork (default), eventlet, gevent, solo or threads),在启动celery worker时,-P为gevent,即指定gevent为POOL。

gevent简介的更多相关文章

  1. gevent调度流程解析

    gevent是目前应用非常广泛的网络库,高效的轮询IO库libev加上协程(coroutine),使得gevent的性能非常出色,尤其是在web应用中.本文介绍gevent的调度流程,主要包括geve ...

  2. Python中Paramiko协程方式详解

    什么是协程 协程我们可以看做是一种用户空间的线程. 操作系统对齐存在一无所知,需要用户自己去调度. 比如说进程,线程操作系统都是知道它们存在的.协程的话是用户空间的线程,操作系统是不知道的. 为什么要 ...

  3. 百万年薪python之路 -- 并发编程之 协程

    协程 一. 协程的引入 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两 ...

  4. Python之路【第一篇】:Python简介和入门

    python简介: 一.什么是python Python(英国发音:/ pa θ n/ 美国发音:/ pa θɑ n/),是一种面向对象.直译式的计算机程序语言. 每一门语言都有自己的哲学: pyth ...

  5. python gevent 协程

    简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...

  6. gunicorn 简介

      gunicorn是一个python Wsgi http server,只支持在Unix系统上运行,来源于Ruby的unicorn项目.Gunicorn使用prefork master-worker ...

  7. Python之路【第一篇】:Python简介和入门

    python简介: 一.什么是python Python(英国发音:/ pa θ n/ 美国发音:/ pa θɑ n/),是一种面向对象.直译式的计算机程序语言. 每一门语言都有自己的哲学: pyth ...

  8. Python之celery的简介与使用

    celery的简介   celery是一个基于分布式消息传输的异步任务队列,它专注于实时处理,同时也支持任务调度.它的执行单元为任务(task),利用多线程,如Eventlet,gevent等,它们能 ...

  9. python 全栈开发,Day43(引子,协程介绍,Greenlet模块,Gevent模块,Gevent之同步与异步)

    昨日内容回顾 I/O模型,面试会问到I/O操作,不占用CPU.它内部有一个专门的处理I/O模块.print和写log 属于I/O操作,它不占用CPU 线程GIL保证一个进程中的多个线程在同一时刻只有一 ...

随机推荐

  1. Oracle--利用监听器日志监控访问该数据库的客户端IP

    服务器10.10.10.168  数据库seineebs 客户端 10.10.10.14  用户guipeng.zhang 查看监听器状态: 在本机利用PL/SQL工具连接该数据库 查看监听器日志:一 ...

  2. [CSP-S模拟测试]:计数(DP+记忆化搜索)

    题目描述 既然是萌萌哒$visit\text{_}world$的比赛,那必然会有一道计数题啦!考虑一个$N$个节点的二叉树,它的节点被标上了$1\sim N$的编号.并且,编号为$i$的节点在二叉树的 ...

  3. 续上文,Unity3D面试ABC

    http://www.unitymanual.com/blog-3573-685.html 最先执行的方法是: 1.(激活时的初始化代码)Awake,2.Start.3.Update[FixUpdat ...

  4. 重新理解了重定向,利用重定向可以防止用户重复提交表单(兼谈springmvc重定向操作)

    自己用springmvc框架有一段时间了,但是都还一直分不清楚什么时候应该用转发,什么时候应该用重定向.可能用转发的情形太多了,以致于自己都忘记了还有重定向. 当用户提交post请求之后,刷新页面就会 ...

  5. codeforces 704B - Ant Man [想法题]

    题目链接:http://codeforces.com/problemset/problem/704/B ------------------------------------------------ ...

  6. react 类样式的一些使用方法

    在 css类不想使用穿透的状态,可以再webpack配置  modules:true,它位于css-loader下,此外调用css的类时可能会自动生成一个hash值,这时候如果想显示本来的名字,可以打 ...

  7. Java接口继承

    Java中接口可以继承接口,并且可以多继承.

  8. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_01 Collection集合_7_增强for循环

    collections实现了interable接口.实现了interable接口就可以使用Foreach int i是临时 变量

  9. PL/SQL Developer 报错Dynamic Performance Tables not accessible, Automatic Statistics disabled for this session You can disable statistics in the preference menu, or obtain select priviliges on the V$ses

    可以从以下几个方面考虑: 1)单独给用户授动态性能视图的权限: SQL> grant select on V_session  to user; SQL> grant select on  ...

  10. 编译的时候出现"/usr/bin/ld: cannot find -lz

    编译的时候出现"/usr/bin/ld: cannot find -lz"错误,需要安装zlib-dev这个包,在线安装命令为:apt-get install zlib1g-dev ...