首页 > 网络 > 云计算 >

世界杯外围投注官网

2016-10-09

openstacknova基础知识——eventlet。openstack的Eventlet库在openstack服务中上镜率很高,尤其是在 服务的多线程 和 WSGI服务器并发处理请求的情况下,深入理解。

openstack的Eventlet库在openstack服务中上镜率很高,尤其是在 服务的多线程WSGI服务器并发处理请求的情况下,深入理解。

eventlet库很有必要。这也是进入nova世界的关键,涉及一个很重要的概念:"协程"。

eventlet库是由second life开源的高性能网络库,从eventlet的源码可以知道,其主要依赖两个关键的库:

(1)、greenlet

(2)、select.epoll(或者epoll类似的库)

greenlet库是其并发的基础,eventlet库简单的对其进行封装之后,就构成了GreenTread。

select库中的epoll则是默认的网络通信模型。正式由于这两个库的相对独立性,可以从两方面学习eventlet库。

这是eventlet的官方网站:http://eventlet.net/ (建议阅读自己需要的部分,等后面用到再来看,文档介绍比较全面)

一、什么是协程

1、协程是一条执行序列,拥有自己独立的栈、局部变量和指令指针,同时又与其他的协同程序共享全局变量和其他大部分东西

2、线程与协程主要区别:

一个多线程的程序可以同时运行几个线程,而协同程序需要彼此协作运行。

一个具有多个协程的程序在任何时刻只能运行一个协程,并且正在执行的协程只会在自己显示的挂起时,执行才会暂停。

二、协程的好处

1、每个协程都有自己私有的栈和局部变量

2、同一时间只有一个协程在运行,无需对全局变量进行加锁

3、顺序可控,完全是由程序控制执行的顺序。而通常多线程一旦启动,运行时序是没法预测的,因此通常会给测试所有的程序带来

问题。

三、eventlet是什么,用来做什么

1、eventlet是python库函数,一个是处理和网络相关的,另一个可以通过协程实现并发

2、在eventlet里,把“协程”叫做greenthread(绿色线程)。

所谓并发,就是开启了多个greenthread(绿色线程),并且对这些greenthread进行管理,以实现非阻塞式的I/O。

比如说用eventlet可以很方便的写一个性能很好的web服务器,或者是一个效率很高的网页爬虫,这都归功于eventlet的"绿色线

程",以及对“绿色线程”的管理机制。eventlet为了实现“绿色线程”,竟然对python的和网络相关的几个标准库函数进行了改

写,并且可以以补丁(patch)的方式导入到程序中,因为python的库函数只支持普通的线程,而不支持协程,eventlet称之为“绿

化”。

四、几个主要API的理解

1、Greenthread Spawn(产生greenthread绿色线程)

主要有3个函数可以创建绿色线程:

(1)spawn(func, *args, **kwargs)

创建绿色线程去运行fun这个函数,后面的参数是传递给这个函数的参数。

返回值是eventlet.GreenThread对象,这个对象可以用来接受func函数运行的返回值。

在绿色线程池还没有满的情况下,绿色线程一被创建就会立刻执行。线程被创建出来,肯定是要有一定的任务要去执行,这里

直接把函数当作参数传递进去,去执行一定的任务,就好像标准库中的线程用run()方法去执行任务一样。

(2)spawn_n(func, *args, **kwargs)

这个函数和spawn()类似,不同的就是它没有返回值,因而更加高效,这种特性,使它也有存在的价值。

(3)spawn_after(seconds, func, *args, **kwargs)

这个函数和spawn()基本上一样,都有一样的返回值,不同的是它可以限定在什么时候执行这个绿色线程,即在seconds秒之

后,启动这个绿色线程。

2、Greenthread Control(控制greenthread)

(1)sleep(seconds=0)

中止当前的绿色线程,以允许其它的绿色线程执行

(2)eventlet.GreenPool

这是一个类,在这个类中用set集合来容纳所创建的绿色线程,并且可以指定容纳线程的最大数量(默认是1000

个),它的内部是用Semaphore和Event这两个类来对池进行控制的,这样就构成了线程池。其中,有几个比较重要的方法:

running(self):返回当前池中的绿色线程数

free():返回当前池中仍可容纳的绿色线程数

spawn()、spawn_n():创建新的绿色线程

starmap(self, function, iterable) 和 imap(self, function, *iterables):

前者实现的是从iterable中取出每一项作为function的参数来执行,后者则是分别从iterables中各取一项,作为function

的参数去执行。

如: imap(pow, (2,3,10), (5,2,3)) --> 32 9 1000 元祖

starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000 元祖列表

(3)eventlet.GreenPile

这也是一个类,而且是一个很有用的类,在它内部维护了一个GreenPool对象和一个Queue对象

这个GreenPool对象可以是从外部传递进来的,也可以是在类内部创建的,GreenPool对象主要是用来创建绿色线程的,即在

GreenPile内部调用了GreenPool.spawn()方法。Queue对象则是用来保存spawn()方法的返回值的,即Queue中保存的是

GreenThread对象。并且它还实现了next()方法,也就意味着GreenPile对象具有了迭代器的性质。所以如果我们要对绿色线

程的返回值进行操作的话,用这个类是再好不过的了。

(4)eventlet.Queue(这个类不是很清楚,先写下来等后面通过实例用到的时候再来理解)

说到队列就不得不画个类图了,基类是LightQueue,它实现了大部分的队列的常用方法。它是用collections做为实现队列

的基本数据结构的。而且这个LightQueue的实现,不单单实现了存取操作,我觉得在本质上它实现了一个生产者和消费者问

题,定义了两个set()类型的成员变量putters和getters,前者用来存放在队列满时,被阻塞的绿色线程,后者用来存放当队

列空时,被阻塞的绿色线程。类中的putting()和getting()方法就是分别得到被阻塞的绿色线程的数量。

Queue继承了LightQueue,并且又增加了它自己的两个方法:task_done()和join()。

(1)、task_done()是被消费者的绿色线程所调用的,表示在这个项上的所有工作都做完了。

(2)、join()是阻塞,直到队列中所有的任务都完成。LifoQueue和PriorityQueue是存放数据的两种不同的方式。

\
3、Network Convenience Functions(和网络相关的函数)

这些函数定义在convenience.py文件中,对和socket相关的网络通信进行了包装,注意,这里用的socket是经过修改后的

socket,以使它使用绿色线程,主要有以下一个函数:

(1)connect(addr, family=socket.AF_INET, bind=None)

主要执行了以下几个步骤:新建了一个TCP类型的socket,绑定本地的ip和端口,和远程的地址进行连接

(2)listen(addr, family=socket.AF_INET, backlog=50)

过程和connect()类似,只是把connect()换成了listen(),backlog指定了最大的连接数量

(3)serve(sock, handle, concurrency=1000)

这个函数直接创建了一个socket服务器,在它内部创建了一个GreenPool对象,默认的最大绿色线程数是1000,

然后是一个循环来接受连接

(4)wrap_ssl(sock, *a, **kw)

给socket加上ssl(安全套接层),对数据进行加密

其他的API函数就先不管了,等以后用到了再进行分析吧,下面看几个官方的例子:

五、举例

1、网络爬虫,用一个绿色线程池获取urls的信息。用到绿色线程池和imap()函数。

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(200) 世界杯外围投注官网创建绿色线程池对象,可以指定数量
for body in pool.imap(fetch, urls): 世界杯外围投注官网协程根据指定要执行的函数依次执行获得url的信息
    print("got body", len(body))

2、socket服务器(感觉很重要)

import eventlet
def handle(fd):
    print "client connected"
    while True:   世界杯外围投注官网典型的读取文件的操作
        世界杯外围投注官网 pass through every non-eof line  
        x = fd.readline()
        if not x: break
        fd.write(x)
        fd.flush()         世界杯外围投注官网将文件内容刷新到硬盘中
        print "echoed", x,
    print "client disconnected"

print "server socket listening on port 8000"   世界杯外围投注官网服务器监听程序,响应客户端的请求  
server = eventlet.listen((&世界杯外围投注官网39;127.0.0.1&世界杯外围投注官网39;, 8000))  世界杯外围投注官网 (IP地址, 端口) 元祖的形式表示
pool = eventlet.GreenPool(200)    世界杯外围投注官网绿色线程池,允许并行访问
while True:
        new_sock, address = server.accept() 世界杯外围投注官网阻塞,等待客户端连接   返回socket对象和客户端的  IP地址和端口号
        print "accepted", address
        pool.spawn_n(handle, new_sock.makefile(&世界杯外围投注官网39;rw&世界杯外围投注官网39;))  世界杯外围投注官网创建新的绿色线程然后去执行

new_socket.makefile(&世界杯外围投注官网39;rw&世界杯外围投注官网39;) //创建一个与该套接字相关连的文件,然后通过此文件操作套接字对象

输出结果:

客户端:

\

服务器端:

\

3、使用GreenPile的例子(这个例子自己可以看看哈)

import eventlet
from eventlet.green import socket
def geturl(url):
    c = socket.socket()
    ip = socket.gethostbyname(url)
    c.connect((ip, 80))
    print &世界杯外围投注官网39;%s connected&世界杯外围投注官网39; % url
    c.sendall(&世界杯外围投注官网39;GET /\r\n\r\n&世界杯外围投注官网39;)
    return c.recv(1024)
urls = [&世界杯外围投注官网39;www.google.com&世界杯外围投注官网39;, &世界杯外围投注官网39;www.yandex.ru&世界杯外围投注官网39;, &世界杯外围投注官网39;www.python.org&世界杯外围投注官网39;]
pile = eventlet.GreenPile()
for x in urls:
    pile.spawn(geturl, x)
世界杯外围投注官网 note that the pile acts as a collection of return values from the functions  
世界杯外围投注官网 if any exceptions are raised by the function they&世界杯外围投注官网39;ll get raised here  
for url, result in zip(urls, pile):
    print &世界杯外围投注官网39;%s: %s&世界杯外围投注官网39; % (url, repr(result)[:50])
相关文章
最新文章
热点推荐