eventlet详解
正真工作才发现很懒,没这么多时间写文,毕竟小白,参照大神写的,不喜勿喷
1.eventlet是什么
eventlet - 具有WSGI支持的异步框架
eventlet是python库函数,一个是处理和网络相关的,另一个可以通过协程实现并发
可以实现'并发'(绿色线程),非阻塞
对Python库函数改写,支持协程
绿色线程和普通线程区别
1. 绿色线程几乎没有开销,不用像保留普通线程一样保留“绿色线程”,每一个网络连接对应至少一个“绿色线程”;
2. 绿色线程需要人为的设置使其互相让渡CPU控制权,而不是抢占。绿色线程既能够共享数据结构,又不需要显式的互斥控制,因为只有当一个绿色线程让出了控制权后其他的绿色线程才能访问彼此共享的数据结构。
下图是eventlet中协程、hub、线程、进程之间的关系:

2.eventlet依赖的库
1.greenlet
greenlet库是其并发的基础,eventlet库简单的对其进行封装之后,就构成了GreenTread。
2.select.epoll
select库中的epoll则是默认的网络通信模型。正式由于这两个库的相对独立性,可以从两方面学习eventlet库。
3.协程
协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。多核CPU使用多进程+协程
4.迭代器
4.1可迭代对象(iterable)实现了__iter__()方法的对象,通过调用iter()方法可以获得一个迭代器(Iterator)。
4.2迭代器(iterator)是实现了iterator.__iter__()和iterator.__next__()方法的对象
4.3iterator是消耗型的,即每一个值被使用过后,就消失了
4.4for ... in ...语句的工作原理--即是一个生成器把所有数全推出来
4.5.yield用法,先返回了yield表达式的值,然后中断,等待next()调用再执行.
4.6.generator其实有第2种调用方法(恢复执行),即通过send(value)方法将value作为yield表达式的当前值,要确保,generator是在yield处被暂停了,才能传值,可以用next()方法
5.GreenLet
6.几个主要API的理解
6.1 greenlet
1.每个协程都有自己的私有stack及局部变量;
2.同一时间内只有一个协程在运行,故无须对某些共享变量加锁;
3.协程之间的执行顺序,完成由程序来控制;
6.2 GreenThread
eventlet中对greenlet进行了简单的封装,GreenThread的调度通过hub来实现
6.3 GreenPool
该模块提供对 greenthread 池的支持。
class eventlet.greenpool.GreenPool(size=1000)
类主要方法:
1. free()
2. imap(function, *iterables)
3. resize(new_size)
4. running()
5. spawn(function, *args, **kwargs)
6. spawn_n(function, *args, **kwargs)
7. starmap(function, iterable)
8. waitall()
9. waiting()
1.
free()
返回当前对象中可用的greenthreads。
如果为 0 或更少,那么 spawn() 和 spawn_n() 将会阻塞调用 greenthread 直到有新的可用的 greenthread 为止。
至于为什么此处可能返回负值,请查看3. resize()
2.
imap(function, *iterables)
效果等同于 itertools.imap() ,在并发和内存使用上等同于 starmap() 。
例如,可以非常方便地对文件做一些操作:
def worker(line):
return do_something(line)
pool = GreenPool()
for result in pool.imap(worker, open("filename", 'r')):
print(result)
3.
resize(new_size)
改变当前允许同时工作的 greenthreads 最大数量
如果当前有多于 new_size 的 greenthreads 处于工作中,它们可以完成自己的执行,只不过此时不许任何的新 greenthreads 被分配。只有当足够数量的 greenthreads 完成自己的工作,然后工作中的 greenthreads 总数低于 new_size 时,新的 greenthreads 才能被分配。在此之前,free() 的返回值将会使负的。
4.
running()
返回当前池子中正在执行任务的 greenthreads 。
5.
spawn(function, *args, **kwargs)
从当前的池子中孵化一个可用的greenthread,在这个 greenthread 中执行 function ,参数 *args, **kwargs 为传给 function 的参数。返回一个 GreenThread 对象,这个对象执行着 function ,可以通过该 GreenThread 对象获取 function 的返回值。
如果当前池子中没有空余的 greenthread ,那么该方法阻塞直到有新的可用的 greenthreads 被释放。
该函数可以重用, function 可以调用同一个 GreenPool 对象的 spawn 方法,不用担心死锁。
6.
spawn_n(function, *args, **kwargs)
创建一个 greenthread 来运行 function,效果等同于 spawn()。 只不过这个函数返回 None,即丢弃 function 的返回值。
7.
starmap(function, iterable)
等同于 itertools.starmap(),除了对于可迭代对象中的每一个元素,都会在一个 greenthread 里面执行 func 。 并发的上限由池子的容量限制。在实际的操作中, starmap() 消耗的内存与池子的容量成比例,从而格外适合遍历特别长的输入列表。
8.
waitall()
等待池子中的所有 greenthreads 完成工作。
9.
waiting()
返回当前等待孵化的 greenthreads 数。
6.4 GreenPile(绿色线程池,可以有效的控制并发)
pile = eventlet.GreenPile(pool)
# 执行函数,把值放进去,函数可以重用, function 可以调用同一个 GreenPool 对象的 spawn 方法,不用担心死锁。
pile.spawn(func,value)
一般
1. next()
等待下一个结果,挂起当前的 greenthread 直到结果可用为止。 当没有更多的结果时,抛出 StopIteration 异常。
2. spawn(func, *args, **kw)
在它自己的 greenthread 中运行 func,结果储存在 GreenPile 对象中,可以迭代该对象获取这些结果。
7.例子
7.1 爬虫
import eventlet
from eventlet.green import urllib2
urls = ["http://www.google.com/intl/en_ALL/images/logo.gif",
"https://wiki.secondlife.com/w/images/secondlife.jpg",
"http://us.i1.yimg.com/us.yimg.com/i/ww/beta/y3.gif"]
def fetch(url):
return urllib2.urlopen(url).read()
pool = eventlet.GreenPool()
for body in pool.imap(fetch, urls):
print("got body", len(body))
第2行引入绿化后的 urllib2,除了使用绿化后的套接字外,与原有的标准库完全相同。
第11行创建一个绿色线程池,此处缺省容量为1000,线程池可以控制并发,限制内存消耗的上限;
第12行遍历并行调用函数 fetch 后的结果,imap 可以并行调用函数 fetch ,返回结果的先后顺序和执行的先后顺序相同。
这个例子的关键就在于客户端起了若干的绿色线程,并行收集网络爬取的结果,同时由于绿色线程池加了内存帽,也不会因为url列表过大而消耗过多的内存。
7.2 简单socket服务器
import eventlet
def handle(client):
while True:
c = client.recv(1)
if not c: break
client.sendall(c)
server = eventlet.listen(('0.0.0.0', 6000))
pool = eventlet.GreenPool(10000)
while True:
new_sock, address = server.accept()
pool.spawn_n(handle, new_sock)
server = eventlet.listen(('0.0.0.0', 6000)) 一句创建一个监听套接字;
pool = eventlet.GreenPool(10000) 一句创建一个绿色线程池,最多可以容纳10000个客户端连接;
new_sock, address = server.accept() 一句很特殊,由于这里创建的服务器套接字是经过绿化的,所以当多个连接到来时在accept()这里不会阻塞,而是并行接收
pool.spawn_n(handle, new_sock) 一句为每一个客户端创建一个绿色线程,该绿色线程不在乎回调函数 handle 的执行结果,也就是完全将客户端套接字交给回调 handle 处理。
7.3
Feed 挖掘机
该用例下,一个服务端同时也是另一个服务的客户端,比如代理等,这里 GreenPile 就发挥作用了。
下面的例子中,服务端从客户端接收 POST 请求,请求中包括含有 RSS feed 的URL,服务端并发地到 feed 服务器那里取回所有的 feed 然后将他们的标题返回给客户端:
import eventlet
feedparser = eventlet.import_patched('feedparser')
pool = eventlet.GreenPool()
def fetch_title(url):
d = feedparser.parse(url)
return d.feed.get('title', '')
def app(environ, start_response):
pile = eventlet.GreenPile(pool)
for url in environ['wsgi.input'].readlines():
pile.spawn(fetch_title, url)
titles = '\n'.join(pile)
start_response('200 OK', [('Content-type', 'text/plain')])
return [titles]
使用绿色线程池的好处是控制并发,如果没有这个并发控制的话,客户端可能会让服务端在 feed 服务器那里起很多的连接,导致服务端被feed服务器给 ban 掉。
总结:
1. Greenthread Spawn(产生greenthread绿色线程)
spawn(func, *args, **kwargs)
2. Greenthread Control(控制greenthread)
eventlet.GreenPool;eventlet.GreenPile;eventlet.Queue
3. Network Convenience Functions(和网络相关的函数)
绿化socket
eventlet详解的更多相关文章
- qemu-img check命令详解
1.问题现象 生产环境上,对计算节点文件系统修复,导致某些虚机的镜像文件数据丢失,出现异常,最终造成虚机无法启动,查看对应计算节点的nova日志,报如下错误 nova-compute: File &q ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- Git初探--笔记整理和Git命令详解
几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
随机推荐
- Linux 套接字编程 - select
select 可以感知文件表述符集合中的变化,如果办fd0(即标准输入)放入select的read fd set,发现只有按回车的时候select才会返回.查了下要把终端的缓冲大小设为1,这样就能实现 ...
- 00字体图标iconfont的制作与使用--阿里矢量图库
一.iconfont的使用范围 在工作当中,经常会用到嵌在元素里的小图标 在这种情况下,如果使用<img>标签或者用作背景图片,也能实现这种效果.但是如果这么做的话,就必须把图片一个个切下 ...
- vue的拖拽文件
<div ref='select_frame' ondragstart="return false">//防止跳转 </div> this.$refs.se ...
- 用Webstorm 运行React-native 工程时,出错:xcrun: error: unable to find utility "instruments", not a developer tool or in PATH
解决方法:在 终端执行如下命令 sudo xcode-select -s /Applications/Xcode.app/Contents/Developer/ 注意:前提是你已经安装了xcode
- Windows漏洞利用技术概述
Windows漏洞利用技术总结 1. 前言 本文是我对漏洞利用技术的学习总结,也是自己践行QAD (Questions.Answer.Discussions)的一次实践.本文通过阅读几位大牛的文章.演 ...
- python接口测试-项目实践(五) 实际结果与预期结果对比之 接口对比
五 与开发接口对比 1 分别将三个接口封装成三个函数,传入接口参数,返回提取并处理后的各字段. 拼接字符串作为单独的函数. def api_1(code): 发送请求获取响应 提取响应数据 响应数据转 ...
- 小故事学设计模式之Observer : (三) 老婆帮忙订机票
(IT的事就是过场多,过场多了就容易忘,所以我们不妨看一个记一个,这也是一个办法,顺便还能跟同行们交流一下) 要和老婆一起回老家了, 成都离我们安徽太远, 两个人飞一下过去就要花掉近三千块, 于是我 ...
- python manage.py startapp app 时候报错No module named _sqlite3
python manage.py startapp app 报错如下: File "manage.py", line 10, in <module> execut ...
- bzoj2004 [Hnoi2010]公交线路
Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距 离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决 ...
- Jupyter notebook 的一个问题
Traceback (most recent call last): File , in get value = obj._trait_values[self.name] KeyError: 'all ...