openstack中eventlet使用

Posted mainred

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了openstack中eventlet使用相关的知识,希望对你有一定的参考价值。

openstack中使用eventlet的协程来实现并发。

第一种,使用eventlet.GreenPool来管理绿色线程

如l3-agent在开启了8个绿色线程来处理router消息

def _process_routers_loop(self):
    pool = eventlet.GreenPool(size=8)
    while True:
        pool.spawn_n(self._process_router_update)

  

第二种是在oslo.messaging中创建接消息的进程直接创建绿色线程

eventlet.spawn()

 

那么在绿色线程到底都走了哪些流程呢?

 

在使用greenlet来创建新的对象的时候,会用调用green_new(tp_new)来创建,后序使用green_init(__init__)来做初始化。在用green_new创建对象时,将此greenlet对象的parent设置为当前的greenlet。

static PyObject* green_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	PyObject* o = PyBaseObject_Type.tp_new(type, ts_empty_tuple, ts_empty_dict);
	if (o != NULL) {
		if (!STATE_OK) {
			Py_DECREF(o);
			return NULL;
		}
		Py_INCREF(ts_current);
		((PyGreenlet*) o)->parent = ts_current;
	}
	return o;
}

在初始化时将设置了运行函数信息,self->run_info = nrun。

在引用greenlet库时,会引用main greenlet,这个是对用户透明的库,所以在使用greenlet库时,除了显式创建的greenlet运行结束之后,还有会运行main greenlet继续执行。

在引用模块的时候会调用initModuleName函数来做初始化,对于greenlet库有对应的initgreenlet函数,其中调用了green_create_main来创建main greenlet

static PyGreenlet* green_create_main(void)
{
    PyGreenlet* gmain;
    PyObject* dict = PyThreadState_GetDict();
/* create the main greenlet for this thread */
    gmain = (PyGreenlet*) PyType_GenericAlloc(&PyGreenlet_Type, 0);

    gmain->stack_start = (char*) 1;
    gmain->stack_stop = (char*) -1;
    gmain->run_info = dict;
    Py_INCREF(dict);
    return gmain;
}

 

在调用 gr.switch的时候会做如下三个动作来完成切换。

  • 保存线程状态,即EIP
  • 进行C栈切换,汇编实现
  • 恢复目标线程状态,即跳转执行位置

 

 

static PyObject* green_new(PyTypeObject *type, PyObject *args, PyObject *kwds){PyObject* o = PyBaseObject_Type.tp_new(type, ts_empty_tuple, ts_empty_dict);if (o != NULL) {if (!STATE_OK) {Py_DECREF(o);return NULL;}Py_INCREF(ts_current);((PyGreenlet*) o)->parent = ts_current;}return o;}

以上是关于openstack中eventlet使用的主要内容,如果未能解决你的问题,请参考以下文章

raise RuntimeError('你需要使用 eventlet 服务器。'

我无法安装 eventlet/gevent/greenlet

如何组合多处理和eventlet

我应该在 celery 中使用 prefork、eventlet 或 gevent 哪个池类?

使用 Eventlet 从 WSGI 应用程序获取客户端 IP 地址

python超时处理方法eventlet的eventlet.Timeout