Flask + Gevent PyWSGI + MySQL Connector:池中的get_connection有时挂起

问题描述

我正在使用Gevent PyWsgiMysqL Connector作为数据库驱动程序来开发Flask服务器。在monkey_patch使其并发服务多个请求之后,我发现有时我的服务器挂起了两个或多个并发请求,并且我必须重新启动服务器才能使其工作。 详细信息:

  • 我设置了MysqL连接池(pool_size = 10),并在应用程序上共享了该单个池实例。
class PoolManager:
    def __init__(self,*args,**kwargs):
        self.args = args
        self.kwargs = kwargs
        self._init()

    def _init(self):
        self._pool = MysqLConnectionPool(*self.args,**self.kwargs)

    def get_connection(self):
        #logging greenlet id
        print("Start get connection from pool....")
        print("GID {}".format(id(gevent.getcurrent()))) 
        new_cnx = self._pool.get_connection()
        print(" -------CONN_ID: {}".format(new_cnx.__getattr__("connection_id")))
        return new_cnx
  • 开始运行时,一切似乎都还不错,我看到该池初始化了与MysqL的10个连接,并且工作正常。每个即将到来的请求已同时得到处理。
  • 一段时间后,我又发出了2个请求。.stdout被卡在上面的日志行中:
Start get connection from pool....
GID 123xxxxx
Start get connection from pool....
GID 321xxxxx

然后什么也没有发生。 MysqL连接(通过show processlist)正在全部休眠,我的服务器已挂起。 所以,我的问题是:

  • 在这里有比赛条件吗?哪里有问题? Gevent Pywsgi还是MysqL Connector?
  • 这里哪种方法正确? MysqLConnectionPool不能在线程上重用,我应该为每个greenlet初始化每个连接吗?

解决方法

对于gevent,您可能需要特定的mysql模块。 UltraMysql位于: https://github.com/esnme/ultramysql

您应该在此处查看此示例。这在我所有的生产环境中都很好。

Python Postgres psycopg2 ThreadedConnectionPool exhausted