wsgi server:
#!/usr/bin/python
import eventlet
from eventlet importwsgi
def hello_world(env,start_response):
start_response('200 OK', [('Content-Type','text/plain')])
return ['Hello, World!\r\n']
wsgi.server(eventlet.listen(('',8090)), hello_world)
测试:wget http://0.0.0.0:8090 -O - -q; echo "" work well
绿色线程:协程
#!/usr/bin/python
import eventlet
from greenlet importgreenlet
def test1():
print 12
gr2.switch()
print 34
def test2():
print 56
gr1.switch()
print 78
gr1 =greenlet(test1)
gr2 =greenlet(test2)
#gr1.switch()
def fun():
print("----fun---")
eventlet.sleep(1)
print("----fun-end--")
def fun2():
print("----fun2---")
eventlet.sleep(5)
#time.sleep(10) #协程不会切换
print("----fun2-end--")
gt = eventlet.spawn(fun) #创建一个协程,那么什么时候开始调度执行呢? 等到出现可以切换的IO操作就开始执行,可切换的IO操作包括绿化过的IO, 协程的wait,eventlet.sleep, eventlet.event.Event().wait()等
gt2 =eventlet.spawn(fun2)
gt.wait() #协程的执行函数fun退出后,wait返回, wait也是一个IO操作,所以开始切换到其他协程
gt2.wait() # fun2退出后,wait才返回,实际使用时需要定义一个永远不退出协程( eventlet.sleep 无限长时间,或者用 eventlet.event.Event().wait()),由此协程进行wait
Hub构成了 Eventlet 的事件循环,它分发 I/O 事件、调度 greenthread。Hub的存在使得协程被提升为 greenthreads。
Eventlet 有多种hub的实现,所以在使用之前应该选择最适合自己系统的实现:
来自 <http://www.cnblogs.com/Security-Darren/p/4178686.html>
Hub是怎么工作的
hub 有一个主 greenlet,MAINLOOP。当运行中的协程需要进行 I/O 操作时,它会在 hub 中注册一个 listener(这样hub就知道什么时候唤醒它),然后切换到 MAINLOOP (通过 get_hub().switch())。如果有其他准备运行的协程, MAINLOOP 会切换到他们,当他们完成执行或需要 I/O 时,又会将控制权切换给 MAINLOOP。以这样的方式,MAINLOOP 确保了每一个协程在自己有事要完成的时候都能够得到调度。
MAINLOOP只在第一次I/O发生时执行,而且它不是 __main__ 所运行在的那个 greenlet。这种延迟运行的方式解释了为什么不需要显式地调用 dispatch() 方法,也就是说代码不需要重构就可以开始使用 Eventlet。
>>> from eventlet import event
>>>importeventlet
>>>evt =event.Event()
>>>defwaiter():
... print('about towait')
... result =evt.wait()
... print('waited for{0}'.format(result))
>>>_ =eventlet.spawn(waiter) #创建协程
>>> eventlet.sleep(0) #睡眠,开始切换到其他协程
about to wait
>>>evt.send('a') #不会马上唤醒其他协程
>>>eventlet.sleep(0)
waited for a
来自 <http://www.cnblogs.com/Security-Darren/p/4168116.html>
绿色线程组:协程组
#!/usr/bin/python
importeventlet
fromeventlet import wsgi
defhello_world(env, start_response):
start_response('200 OK', [('Content-Type','text/plain')])
return ['good, Hello, World!\r\n']
def fun():
wsgi.server(eventlet.listen(('', 8090)),hello_world)
#wsgi.server(eventlet.listen(('', 8090)), hello_world) #进程不会退出
pool =eventlet.GreenPool(100)
pool.spawn_n(fun) #fun还未得到调度
#如果接下来没有其他代码,则进程退出,因为fun是一个还没启动的协程(还未得到调度)
pool.waitall() #开始启动协程,fun开始调度,也可以用 eventlet.event.Event().wait()启动。本质上waitall是一个绿化的操作,注册wait事件,并切换到MAINLOOP
可以定义多个协程组,只要某一个协程组调用waitall(),则所有的协程组都开始调度
#!/usr/bin/python
importeventlet
fromeventlet import wsgi
importtime
fromeventlet import event
eventlet.monkey_patch()
pool =eventlet.GreenPool(100)
pool2= eventlet.GreenPool(100)
deffun1():
print("fun1---begin")
eventlet.sleep(2)
print("fun1---end")
deffun2():
print("fun2---begin")
eventlet.sleep(2)
pool2.spawn(fun1) # pool.spawn(fun1)
print("fun2---after spawnfun1")
time.sleep(10) #time.sleep被hook了,实际执行的是eventlet.sleep
print("fun2---end")
deflog_exceptions(gt):
print("log_exceptions")
defrun_forever():
while True:
print("run_forever")
eventlet.sleep(1)
pool.spawn(run_forever)
pool2.spawn(fun2)
pool.waitall()
#evt =event.Event()
#evt.wait()
#!/usr/bin/python
import eventlet
from eventlet importwsgi
def hello_world(env,start_response):
start_response('200 OK', [('Content-Type','text/plain')])
return ['good, Hello, World!\r\n']
def fun():
print("server---begin")
wsgi.server(eventlet.listen(('', 8090)),hello_world)
def fun2():
print("fun2---begin")
eventlet.sleep(20)
print("fun2---end")
#wsgi.server(eventlet.listen(('',8090)), hello_world)
pool =eventlet.GreenPool(100)
pool.spawn_n(fun2)
pool.spawn_n(fun)
pool.waitall() #先执行fun2,fun2 sleep之后再执行fun,所有协程执行完毕之后,waitall就返回,程序结束。当然wsgi.serve是不会结束的(内部有while不断循环)