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 的背景. ...
随机推荐
- redux基本使用
redux数据流向 基本使用
- Zepto结合Swiper的选项卡
我们昨天说了关于Angular的选项卡,那今天就说一下Swiper的选项卡吧! 今天的选项卡是Zepto结合Swiper的选项卡,咱么明天再说纯纯的Swiper的吧! 既然是关于Zepto和Swipe ...
- git push & git pull 推送/拉取分支
git push与git pull是一对推送/拉取分支的git命令. git push 使用本地的对应分支来更新对应的远程分支. $ git push <远程主机名> <本地分支名& ...
- 性能优化小Tips
Performance Tips 这篇文章主要是介绍了一些小细节的优化技巧,当这些小技巧综合使用起来的时候,对于整个App的性能提升还是有作用的,只是不能较大幅度的提升性能而已.选择合适的算法与数据结 ...
- 夜色的 cocos2d-x 开发笔记 01
现在我们来实现在屏幕上出现一只飞机的效果. 首先我们要建立一个场景,显示在屏幕上,创建一个类,RunScence,现在你的项目目录应该是这个样子的. 之前没学过C++,.h文件我理解就是一个声明文件, ...
- Windows8中如何打包和安装一个本地的Metro类型应用(转)
Windows8中如何打包和安装一个本地的Metro类型应用 (转自:http://software.intel.com/zh-cn/blogs/2012/05/09/windows8metro) 微 ...
- Siebel Tools配置
默认安装的Siebel+Tools,Tools登陆时有3个选项:Local.Sample.Server,具体涵义如下: Local:指本地数据库.按照Siebel开发建议,开发人员需要从Siebel ...
- 最新一道面試題目,input: int[1,1,2,2,2,3,3,3],output [3,2,1],要求按照數字出現的次數從多到少排列元素。
面試當時沒有及時答出來,感覺當時在面試官的提示下跑偏了.想用兩個數組來mapping key和value然後對等排序,但是因為面試官讓用Array.sort而沒想好有什麼好辦法,結果可想而知.但是題目 ...
- laravel 接入蚂蚁金服SDK(以支付宝APP支付为例)开发步骤
一.创建应用及配置 首先需要到蚂蚁金服开放平台(https://docs.open.alipay.com)注册应用,获取应用id(APP_ID),并且配置应用,主要是签约应用,这个需要审核,一般2-5 ...
- 《3D打印:从想象到现实》:基本没发现独到之处
本书汇总了3D打印的相关咨询:原理.可能的或已经实现的应用.商业模式等等.由于3D打印是最近媒体上比较热的信息,对我来说书中的大部分内容都没有独到之处,都是已知的.