Openstack nova 热迁移绿色thread分析

在分析云主机热迁移的时候,下面函数中有绿色线程,今天回过头来分析一下这里面绿色线程。

def _live_migration(self, context, instance, dest, post_method,
                    recover_method, block_migration,
                    migrate_data):
    """Do live migration.
    This fires off a new thread to run the blocking migration
    operation, and then this thread monitors the progress of
    migration and controls its operation
    """
    #上面注释可以理解为:由于迁移操作会阻塞,需要一个新的thread 来执行迁移操作,本thread(现有代码    #所在的thread)监控迁移并处理。
        
    dom = self._host.get_domain(instance)
    #创建绿色线程,来执行迁移,注意spawn相当于注册了事件处理函数,此处并没有开始调用。
    opthread = utils.spawn(self._live_migration_operation,
                                 context, instance, dest,
                                 block_migration,
                                 migrate_data, dom)
    #创建event对象,下文中会和opthread进行关联。
    finish_event = eventlet.event.Event()

    def thread_finished(thread, event): 
        #此log只能打印Migration operation thread notification,instance是打印不出来的,应        #该是个bug。
LOG.debug("Migration operation thread notification", instance=instance)
        #此处的event=<Event at 0x5ed7d90 result=NOT_USED _exc=None _waiters[0]>
        LOG.debug('thread_finished event=%s', event)
        
        #event.send函数不会引起绿色线程的调度,send函数只是创建一个timer。send函数和wait函数配
        #对使用,因为send会引起wait注册的waiters的调度。
        event.send()
    #opthread 执行完,会调用thread_finished函数,和event结合的目的主要是获取绿色线程执行完的结
    #果,若不想获取执行完的结果,此处代码就没有必要了。
    opthread.link(thread_finished, finish_event)
    # Let eventlet schedule the new thread right away 这里是原始注释
    #此处直接使用time模块,直接使用感觉不规范,应该使用eventlet.sleep(0)
    time.sleep(0)

    try:
        LOG.debug("Starting monitoring of live migration",
                  instance=instance)

        #这里就是文章一开始提到的,迁移监控处理函数。若迁移绿色线程发生了阻塞,那么就可以执行下面函         #数了,_live_migration_monitor中会每隔0.5执行一次读取迁移状态
        self._live_migration_monitor(context, instance, dest,
                                     post_method, recover_method,
                                     block_migration, migrate_data,
                                     dom, finish_event)
    except Exception as ex:
        LOG.warn(_LW("Error monitoring migration: %(ex)s"),
                 {"ex": ex}, instance=instance, exc_info=True)
        raise
    finally:
        LOG.debug("Live migration monitoring is all done",
                  instance=instance)
下面是eventlet模块event.py文件中Event类中的send和wait函数。
eventlet\event.py
def wait(self):
    """Wait until another coroutine calls :meth:`send`.
    Returns the value the other coroutine passed to
    :meth:`send`.

    >>> from eventlet import event
    >>> import eventlet
    >>> evt = event.Event()
    >>> def wait_on():
    ...    retval = evt.wait()
    ...    print("waited for {0}".format(retval))
    >>> _ = eventlet.spawn(wait_on)
    >>> evt.send('result')
    >>> eventlet.sleep(0)
    waited for result

    Returns immediately if the event has already
    occurred.

    >>> evt.wait()
    'result'
    """
    current = greenlet.getcurrent()
    if self._result is NOT_USED:
        self._waiters.add(current)
        try:
            return hubs.get_hub().switch()
        finally:
            self._waiters.discard(current)
    if self._exc is not None:
        current.throw(*self._exc)
    return self._result

def send(self, result=None, exc=None):
    """Makes arrangements for the waiters to be woken with the
    result and then returns immediately to the parent.

    >>> from eventlet import event
    >>> import eventlet
    >>> evt = event.Event()
    >>> def waiter():
    ...     print('about to wait')
    ...     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

    It is an error to call :meth:`send` multiple times on the same event.

    >>> evt.send('whoops')
    Traceback (most recent call last):
    ...
    AssertionError: Trying to re-send() an already-triggered event.

    Use :meth:`reset` between :meth:`send` s to reuse an event object.
    """
    assert self._result is NOT_USED, 'Trying to re-send() an already-triggered event.'
    self._result = result
    if exc is not None and not isinstance(exc, tuple):
        exc = (exc, )
    self._exc = exc
    hub = hubs.get_hub()
    for waiter in self._waiters:
        hub.schedule_call_global(
            0, self._do_send, self._result, self._exc, waiter)
def schedule_call_global(self, seconds, cb, *args, **kw):
    """Schedule a callable to be called after 'seconds' seconds have
    elapsed. The timer will NOT be canceled if the current greenlet has
    exited before the timer fires.
        seconds: The number of seconds to wait.
        cb: The callable to call after the given time.
        *args: Arguments to pass to the callable when called.
        **kw: Keyword arguments to pass to the callable when called.
    """
    t = timer.Timer(seconds, cb, *args, **kw)
    self.add_timer(t)
    return t


  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值