为 DB-API 调用添加 tpool 代理包装器

https://blueprints.launchpad.net/oslo-incubator/+spec/add-tpool-proxy-wrapper

在 Icehouse 发布周期中,为了移除对 eventlet 的依赖,我们移除了 eventlet tpool.Proxy 辅助工具以及相应的配置选项 (use_tpool) 来自 oslo.db 代码。项目应该将这些存储在其源代码树中。此后,我们收到了来自 Nova 和 Cinder 团队的大量反馈,基于他们采用 oslo.db 更改的经验。为了方便 oslo.db 用户,实际上最好在 oslo.db 树中提供与 eventlet tpool.Proxy 的可选集成,作为一个单独的模块。

问题描述

如今,大多数 OpenStack 部署使用 MySQL。不幸的是,最流行的 MySQL Python DBAPI 驱动程序 - MySQL-Python - 在 eventlet green 线程方面存在一个严重问题:作为一个 C 扩展,它会在阻塞的 DB 查询中挂起进程(因为 eventlet 无法对其进行 monkey patch 以强制在从/到套接字的阻塞读/写上进行 green 线程切换)。

eventlet 提供了解决此问题的方法:tpool.Proxy 辅助类旨在包装可能阻塞 green 线程执行的方法/函数。调用将在真实的操作系统线程上下文中执行,该线程知道如何处理 eventlet 线程池,返回时它将切换执行上下文回到 green 线程,从而防止进程挂起。

Common DB 代码曾经提供 use_tpool 选项,该选项为所有数据库方法调用启用了 tpool.Proxy 代理。Nova 至少使用了它。值得一提的是,为了实际使用 use_tpool 选项,必须使用已修补版本的 eventlet,因为 PyPI 发布版和 master HEAD 都不能很好地与 MySQL-Python 配合使用。

在 Icehouse 发布周期中,我们致力于从 Common DB 代码中删除额外的依赖项。eventlet 作为我们认为是不必要的依赖项之一被删除(因为 oslo.db 不应该强制你使用特定的并发模型,也不能对目标项目如何处理并发请求做出任何假设,无论它们是否使用 eventlet green 线程、真实的操作系统线程、多进程等)。但好坏参半,似乎提供与 eventlet tpool.Proxy 的可选集成更好,这样人们就不需要在他们的源代码树中执行此操作了。

提议的变更

为了能够将 oslo.db 与 MySQL-Python DB API 驱动程序和 eventlet tpool.Proxy 调用代理一起使用,我们需要

  1. 提供一个辅助工具,它将根据 use_tpool 配置选项的值,直接调用 DBAPI 方法或使用 tpool.Proxy 包装调用。

  2. 使这个提议的辅助工具在 database 组中注册 use_tpool 配置选项。

  3. 向 oslo.db 添加一个额外的入口点,该入口点将向项目公开 use_tpool 配置选项。

  4. 即使我们在运行时使用 eventlet tpool.Proxy 类,我们也不会将其添加到 oslo.db requirements.txt (我们不希望 eventlet 成为安装时依赖项;如果你使用 eventlet,安装它将由你负责) 和 test-requirements.txt (这将阻止我们在 Python 3.x 版本上运行单元测试;由于我们不需要测试 tpool.Proxy 功能本身,我们可以安全地在测试中模拟这个类)。

备选方案

解决此问题的另一种方法是

  1. 将此辅助工具放入 openstack.common.concurrency 模块中,该模块将依赖于 oslo.db。

  2. 记录,如果有人想将 oslo.db 与 eventlet tpool.ProxyMySQL-Python Python DB API 驱动程序一起使用,他们需要使用 openstack.common.concurrency 模块提供的辅助工具。

此解决方案的优点是,我们不需要将 eventlet 的内容重新添加到 oslo.db 中。

此解决方案的缺点是,我们增加了 oslo.* 库之间的更多依赖关系,并使使用 oslo.db 更加困难(如果用户同时使用 eventlet 和 MySQL,他们可能不清楚为什么需要使用另一个库)。

Impact on Existing APIs

无。

安全影响

无。

性能影响

启用 use_tpool 可以大大提高 DB 绑定服务的 (API) 性能,在使用 eventlet 和 MySQL-Python 时。注意:你仍然需要使用未发布的 eventlet 代码。

Configuration Impact

use_tpool 不会是一个新的配置文件选项,我们只是在 oslo.db 的上下文中引入它。目前,项目从 openstack.common.db 包中获取它。从部署者的角度来看,无需进行任何更改。

开发人员影响

希望使用 oslo.db 与 eventlet tpool.Proxy 调用代理的 OpenStack 项目需要从使用 DBAPI 类切换到新的辅助工具。

实现

负责人

主要负责人

akurilin

其他贡献者

rpodolyaka

里程碑

完成目标里程碑

Juno-1

工作项

  1. 向 oslo.db 添加一个新模块,该模块将引入 tpool.Proxy 辅助工具和 use_tpool 配置选项。

  2. 向 oslo.db 添加一个新入口点,公开 use_tpool 配置选项。

孵化

无。

采用

无。

无。

预计 API 稳定

无。

文档影响

use_tpool 应该标记为实验性的。应该在文档中说明,需要已修补版本的 eventlet 才能使用它。

依赖项

为了正常工作,这依赖于 eventlet 的未发布版本。不过,到目前为止,我们一直在提供 use_tpool 选项。Rackspace 在生产中使用已修补版本的 eventlet。我们将让部署者决定是否启用它(默认值仍然是 False)。

参考资料

一个 PoC 补丁正在审核中

https://review.openstack.org/#/c/96467/

相关的 ML 线程

http://lists.openstack.org/pipermail/openstack-dev/2014-April/033120.html

用于跟踪项目中 use_tpool 使用情况的 Launchpad bug

https://bugs.launchpad.net/nova/+bug/1309297

eventlet tpool 文档

http://eventlet.net/doc/threading.html#module-eventlet.tpool

修复 eventlet 问题的补丁

https://bitbucket.org/eventlet/eventlet/pull-request/29/

注意

本作品采用知识共享署名 3.0 非移植许可协议授权。 http://creativecommons.org/licenses/by/3.0/legalcode