为 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 调用代理一起使用,我们需要
提供一个辅助工具,它将根据
use_tpool配置选项的值,直接调用DBAPI方法或使用tpool.Proxy包装调用。使这个提议的辅助工具在
database组中注册use_tpool配置选项。向 oslo.db 添加一个额外的入口点,该入口点将向项目公开
use_tpool配置选项。即使我们在运行时使用 eventlet
tpool.Proxy类,我们也不会将其添加到 oslo.dbrequirements.txt(我们不希望 eventlet 成为安装时依赖项;如果你使用 eventlet,安装它将由你负责) 和test-requirements.txt(这将阻止我们在 Python 3.x 版本上运行单元测试;由于我们不需要测试tpool.Proxy功能本身,我们可以安全地在测试中模拟这个类)。
备选方案¶
解决此问题的另一种方法是
将此辅助工具放入
openstack.common.concurrency模块中,该模块将依赖于 oslo.db。记录,如果有人想将 oslo.db 与 eventlet
tpool.Proxy和MySQL-PythonPython 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
工作项¶
向 oslo.db 添加一个新模块,该模块将引入
tpool.Proxy辅助工具和use_tpool配置选项。向 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