玩转Openstack之Nova中的协同并发_第1页
玩转Openstack之Nova中的协同并发_第2页
玩转Openstack之Nova中的协同并发_第3页
玩转Openstack之Nova中的协同并发_第4页
玩转Openstack之Nova中的协同并发_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、玩转Openstack之Nova中的协同并发前不久参加了个Opnstack的Meetup,其中有一个来自EasyStack的大大就Nova中的协同并发做了一番讲解,有所感触,本想当天就总结一下,但是由于前段时间工作上比较忙,加上为了履行诺言每天几更的来写设计模式系列性文章,故而拖到今天才写此次的总结。好吧,其实归根结底还是自己太懒了,趁着闲时在补新番小笼包之类的。废话就此打住,开始正文。Python中协程的介绍在此之前,先介绍下Python中的并发,在Python中,并发有三种,分别是:进程:Python中一般使用multiprocessing/subprocess来实现线程:threadin

2、g/thread是Python中用来实现多线程的模块协程(Coroutines):Python中用于处理协程的模块倒是比较多,有eventlet、Twisted、Tulip、asyncio有关进程、协程、线程中的关系图如下所示(图来自EasyStack的大大):想必大家对进程以及线程那是相当的熟悉了,所以就重点介绍下协程:协程源自 Simula 和 Modula-2 语言,但也有其他语言支持。协程更适合于用来实现彼此熟悉的程序组件,如合作式多任务,迭代器,无限列表和管道。 协程最初在1963年被提出。那么协程又有什么特点呢?每个协程都有自己的私有stack以及局部变量。线程我们都知道可以多个同

3、时运行,也就是所谓的多线程,但是同一时间只有一个协程在运行,所以就无须对某些共享变量加锁。由于协程比较轻量级,所以一个线程中可以有多个协程。协程之间的执行顺序,完全由程序来控制。其实协程也就仅仅是一种概念罢了,非操作系统可见,在多种语言中都有实现,一会详细介绍的eventlet就是在Python中实现的一种。Eventlet的介绍eventlet其实就是对greenlet的一个封装,对其进行简单的封装之后,就成了所谓的greenthread,greenlet是一个称为协程(coroutine)的东西。下面上一个greenlet的例子来介绍一下greenlet:1from greenl

4、etimportgreenlet23def test1:4print 125gr2.switch6print 3478def test2:9print 5610gr1.switch11print 781213gr1 =greenlet(test1)14gr2 =greenlet(test2)15gr1.switch 执行结果是:也就是说在这里先定义了两个函数test1,test2以及两个协程gr1,gr2,最后一行g1.switch跳转到 test1 ,它打印12,然后执行gr2.switch,跳转到 t

5、est2 ,打印56,然后又执行了gr1.switch跳转回 test1 ,打印34,然后 test1 就结束,gr1死掉,回到父greenlet,不会再切换到test2,所以不会打印78。在上面的例子中main greenlet就是它们的父 greenlet。eventlet是一个用来处理和网络相关的python库函数,而且可以通过协程来实现并发,在eventlet里,把“协程”叫做greenthread(绿色线程)。所谓并发,就是开启了多个greenthread,并且对这些greenthread进行管理,以实现非阻塞式的I/O。比如说用eventlet可以很方便的写一个性能很好的web服务

6、器,或者是一个效率很高的网页爬虫,这都归功于eventlet的“绿色线程”,以及对“绿色线程”的管理机制。更让人不可思议的是,eventlet为了实现“绿色线程”,竟然对python的和网络相关的几个标准库函数进行了改写,并且可以以补丁(patch)的方式导入到程序中,因为python的库函数只支持普通的线程,而不支持协程,eventlet称之为“绿化”。Eventlet库在OpenStack服务中上镜率很高,尤其是在服务的多线程和WSGI Server并发处理请求的情况下。主要API如下:Greenthread 产:spawn(func, *args, *kwargs): 创建一个绿色线程去

7、运行func这个函数,后面的参数是传递给这个函数的参数。返回值是一个eventlet.GreenThread对象,这个对象可以用来接受func函数运行的返回值。在绿色线程池还没有满的情况下,这个绿色线程一被创建就立刻被执行。其实,用这种方法去创建线程也是可以理解的,线程被创建出来,肯定是有一定的任务要去执行,这里直接把函数当作参数传递进去,去执行一定的任务,就好像标准库中的线程用run方法去执行任务一样。spawn_n(func, *args, *kwargs): 这个函数和spawn类似,不同的就是它没有返回值,因而更加高效,这种特性,使它也有存在的价值。spawn_after(second

8、s, func, *args, *kwargs): 这个函数和spawn基本上一样,都有一样的返回值,不同的是它可以限定在什么时候执行这个绿色线程,即在seconds秒之后,启动这个绿色线程。Greenthread 控制:sleep(seconds=0):中止当前绿色线程,以允许其它绿色线程执行。eventlet.GreenPool: 这是一个类,在这个类中用set集合来容纳所创建的绿色线程,并且可以指定容纳线程的最大数量(默认是1000个),它的内部是用Semaphore和Event这两个类来对池进行控制的,这样就构成了线程池,下面有一些重要的方法:running:返回当前池中的绿色线程数

9、free:返回当前池中可容纳的绿色线程数 spawn:创建新的绿色线程 spawn_n:同上 接着谈谈Openstack中Nova对其的应用。eventlet在nova/cmd/_init_.py中,就直接调用了eventlet的方法,代码如下:from nova import debugger  if debugger.enabled(): eventlet.monkey_patch(os=False, thread=False) else:  eventlet.monkey_pat

10、ch(os=False) 这里在调试器被启动后,关闭线程,然后启用远程调试器。这个就是eventlet.monkey_patch()的方法。这里仅仅是因为dnspython无法支持IPV6,所以使用eventlet的monkeypatch检测一下环境变量的设置是否符合。greenthread在虚机迁移过程中如果看过我写的源码分析,相信对于下面的代码不会陌生:  greenthread.spawn(self._live_migration, context, instance, dest,  post_method, 

11、;recover_method, block_migration, migrate_data) 这个是热迁移中所使用的所调用的由eventlet所封装而成的绿色线程,调用了spawn(func,*args, kwargs)的函数,创建了一个绿色线程去运行live_migration也就是热迁移的函数,返回值是一个eventlet.greenthread的对象,这个对象可以用来接受live_migration运行的返回值。在绿色线程池未满的情况下,就可以直接执行热迁移的函数。greenthread.sleep然后Nova中用到的最多的绿色线程的栗子可能就是time.

12、sleep了吧,下面随便找了几个用到的例子:for cnt in range(max_retry): try: self.plug_vifs(instance, network_info)  break  except processutils.ProcessExecutionError:  if cnt = max_retry - 1:  raise   else:

13、  LOG.warn(_('plug_vifs() failed %(cnt)d. Retry up to '  '%(max_retry)d.'),  'cnt': cnt,   'max_retry': max_retry,   instance=instance)  greenthread.sleep(1)&

14、#160;这个是调用plug_vifs的函数中的greenthread.sleep()的函数调用,这个函数多次的发送请求。except exception.InstanceNotFound: pass greenthread.sleep(0) return disk_over_committed_size 像这样的栗子还有好多,一般情况下,greenthread.sleep()绿色线程的函数是为了中止当前的线程,用来给其它的线程一个执行的机会。其实说的通俗点就是传说中的孔融让梨了,不过此处的梨就是CPU、内存等等一些资源了,绿色池中的

15、空间了之类的,突然发现程序也是那么的有人情味啊loopingcall接下来谈谈用loopingcall实现固定时间间隔运行的函数:def _wait_for_reboot(): state = self.get_info(instance)'state'  if state = power_state.RUNNING: LOG.info(_("Instance rebooted successfully."),  instance=instance)  raise loopingcall.LoopingCallDone()  timer = loopingcall.FixedIntervalLoopingCall(_wait_for_reboot) timer.start(interval=0.5).wait() 这个函数是等待虚机重启的函数,每隔0.5

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论