eventlet



什么是绿色线程,为什么要patch?



关键词:



=   green thread(绿色线程)



启动green thread用来处理处理一些网络相关的工作(?)与一般的线程有两大区别:



1、绿色线程非常便宜,不像一般线程。每一个网络链接至少有一个绿色线程。



2、绿色线程间协同地进行调度,而不是抢占试调度。该方法最大的好处是无需对共享数据枷锁,因为只有正在运行的绿色线程被明确让出后暂停后,其它的绿色线程才能访问数据结构。可以通过检测queues等原始结构,来确定它是否有pending data。





Like Python itself, there should be one, and only one obvious way to do it in Eventlet!



eventlet有很多modules,但大多数的功能可以通过import eventlet获得。



主要接口如下:



eventlet.spawn(func,*args,**kw)



启动一个绿色线程来执行函数func,args和kw为传给func的参数。生成多个绿色线程可以并行完成任务。它的返回值是greenthread.GreenThread,可以用它来获取函数func的返回值。


eventlet.spawn_n(func, *args, **kw)



与spawn一样,速度快,但没有返回值。



eventlet.spawn_after(seconds, func, *args, **kw)



与spawn一样,多一个参数seconds。用来指定多少秒后执行该绿色线程。



eventlet.monkey_patch(all=True, os=False, select=False, socket=False, thread=False, time=False)¶


给module打补丁,使之能够用于绿色线程。如果all=Ture,忽略其它参数,给所有的module打上补丁。如果all=false,将会给每个设为true参数的同名module打上补丁。socket是个例外,当socket=true时,会给socket和ssl modules同时打上补丁。





GreenPool

eventlet中用的最多的当属GreenPool,GreenPool可以理解为一个容纳绿色线程的容器。初始化如下


 

      greenpool = GreenPool(100) #当不指定参数时,默认为1000

该语句生成了一个可以容纳100个绿色线程的线程池,然后可以使用spawn_n()往该线程池中添加线程,并立马执行该绿色线程。



     



这样就往线程池内添加了一个绿色线程,并执行。一共可以添加100个,当然如何一个绿色线程的function执行退出,那该绿色线程会消失。spawn()与spawn_n()的入参和功能相同,只是返回值不同,spawn_n()没有返回值,spawn()返回一个GreenTread对象,利用该对象可以获得function的返回值。



     



该函数用于等待greenpool中的所有绿色线程都执行完成后退出。






绿色线程的协同工作



多个绿色线程如何协同工作呢?这个不太好理解,eventlet内部是如何实现的,这个我也不太了解。不过eventlet的绿色线程是建立在GreenLet基础只上的,可以看看是如何使用的。


#introduce_greenlet.py 
  
 
  
from greenlet import greenlet
 
   

 
   
def test1():
 
   
  
 
   
  
 
   
  
 
   

 
   
def test2():
 
   
  
 
   
  
 
   
  
 
   

 
   
gr1=greenlet(test1)
 
   
gr2=greenlet(test2)
 
   
gr1.switch()
 
  
 
   
 
  

    运行上面代码,可获得结果如下: 
  
 
  

 
   

     12 
   
 
   

     56 
   
 
   

     34
#introduce_greenlet.py 
  
 
  
from greenlet import greenlet
 
   

 
   
def test1():
 
   
  
 
   
  
 
   
  
 
   

 
   
def test2():
 
   
  
 
   
  
 
   
  
 
   

 
   
gr1=greenlet(test1)
 
   
gr2=greenlet(test2)
 
   
gr1.switch()
 
  
 
   
 
  

    运行上面代码,可获得结果如下: 
  
 
  

 
   

     12 
   
 
   

     56 
   
 
   

     34



上面例子可以知道绿色线程之间是如何进行协同工作的。至于我们使用spawn()产生的绿色线程是如何协同工作,内部细节不知道,不过可以理解为与上述例子差不多。每当其中一个在等待时(比如IO等待)就会执行另一个。这样在一个进程内就可以运行多个绿色线程,并且可以共享进程资源(这个指全局变量,函数什么之类的)。



可以想象,一个web server可以同时处理很多请求,如果为每个请求生成一个线程来处理还是有点浪费,用绿色县城就可以很好满足这种需求。每当有一个Request时,就生成一个绿色线程处理。由于数据通过网络传输,等待时间较多,这样就可以让其它绿色线程工作。