3

我们正在构建一个使用 Posgresql 作为服务数据存储的 Python 微服务应用程序。乍一看,Nameko 似乎是一个很好的起点。然而,关于 Concurrency 的 Nameko 文档部分包含以下声明

Nameko 构建在 eventlet 库之上,该库通过“greenthreads”提供并发性。并发模型是带有隐式让步的协程。
隐式屈服依赖于猴子修补标准库,以在线程等待 I/O 时触发屈服。如果您的带有 nameko 的主机服务在命令行上运行,Nameko 将为您应用猴子补丁。
每个工人都在自己的绿色线程中执行。可以根据每个工作人员等待 I/O 所花费的时间来调整并发工作人员的最大数量。
Worker 是无状态的,因此本质上是线程安全的,但依赖项应确保它们对每个 Worker 都是唯一的,或者以其他方式安全地被多个 Worker 并发访问。
请注意,许多使用套接字并且通常被认为是线程安全的 C 扩展可能不适用于 greenthreads。其中有 librabbitmq、MySQLdb 等。

因此,我们的架构师建议 Nameko 不会飞——因为尽管 pyscopg2 Postgresql 驱动程序被宣传为线程安全的:

它的主要特点是Python DB API 2.0规范的完整实现和线程安全(多个线程可以共享同一个连接)。它专为大量多线程应用程序而设计

澄清

上述观察仅对常规线程有效:它们不适用于分叉进程或绿色线程。libpqconnections 不应由分叉进程使用,因此当使用诸如 multiprocessing 之类的模块或诸如 FastCGI 之类的分叉 Web 部署方法时,请确保在分叉之后创建连接。不同的绿色线程也不应该共享连接:有关更多详细信息,请参阅对协程库的支持。

通过链接澄清

警告 Psycopg 连接不是绿色线程安全的,不能由不同的绿色线程同时使用。尝试使用每个线程一个游标一次执行多个命令将导致错误(或在 2.4.2 之前的版本上出现死锁)。因此,建议程序员要么避免在协程之间共享连接,要么使用库友好的锁来同步共享连接,例如用于池化。

正常的服务配置将让服务拥有一个存储库,该存储库具有由线程共享的连接,存储库访问方法使用该连接上的会话,范围为该方法。

我们的架构师建议,即使我们要使用每个线程的连接+会话,因为如果我们在会话上的数据访问调用之间执行其他 I/O 操作,例如文件写入,greenthreads 在给定会话上的隐式屈服方面是如何工作的通过日志记录,我们可能会遭受隐式上下文切换——这可能会导致日志记录后的会话出现问题。

在这种情况下,我们有什么合理的方式可以使用 Nameko,还是像我们的架构师所说的那样注定要失败?有什么方法可以让我们无需编写自己的微服务代码(例如使用Kombu )就可以完成这项工作?

附加说明:此页面上的评论建议有关数据库驱动程序状态:

您可以使用与 SQLAlchemy 兼容的任何数据库驱动程序,只要它与 eventlet 一起使用是安全的。这将包括所有纯 python 驱动程序

它继续列出 pysqlite 和 pymysql。

使用 pg8000 或 py-postgresql 纯 Python 驱动程序会让我们更清楚地了解线程 - 这里的问题是 greenthreads 与使用 C 代码的 pyscopg2/3 驱动程序相结合,还是从根本上 Namekos 使用 greenthreads?

4

0 回答 0