使用django和sqlalchemy的连接池

django-conn-pool的Python项目详细描述


Django Conn游泳池

使用django(>;2.0.0)和sqlalchemy(>;=1.2.7)的mysql连接池。

为什么

如果设置中没有设置CONN_MAX_AGE,django将为每个请求建立一个新的mysql连接,并在请求后关闭它。

因此,如果要处理的连接太多,它将建立太多的连接,直到mysql max_connections用完为止。

然后,mysql将返回错误:ERROR 1040 (08004): Too many connections

对于一个健壮的django项目,有必要维护一个连接池。

原理

Reference: MySQL Connection Pooling with Django and SQLAlchemy

使用sqlalchemy queuepool从连接池创建mysqldb数据库get_new_connection

所以我们只需要自定义一个由连接池管理的数据库,并从连接池中获取新的连接。

pip install mysqlclient
pip install SQLAlchemy

核心代码

import MySQLdb as Database
import sqlalchemy.pool as pool
from sqlalchemy.pool import QueuePool
from django.db.backends.mysql.base import DatabaseWrapper as _DatabaseWrapper


Database = pool.manage(Database, poolclass=QueuePool, **settings.SQLALCHEMY_QUEUEPOOL)

class DatabaseWrapper(_DatabaseWrapper):

    def get_new_connection(self, conn_params):
        # return a mysql connection
        databases = settings.DATABASES
        alias = None
        for _alias in databases:
            if databases[_alias]['NAME'] == conn_params['db']:
                alias = _alias
                break
        client_flag = conn_params['client_flag']

        conn_params = databases[alias]
        return Database.connect(
            host=conn_params['HOST'],
            port=conn_params['PORT'],
            user=conn_params['USER'],
            db=conn_params['NAME'],
            passwd=conn_params['PASSWORD'],
            use_unicode=True,
            charset='utf8',
            client_flag=client_flag,
            sql_mode='STRICT_TRANS_TABLES',
        )

使用量

pip install django-conn-pool

settings.py

# http://docs.sqlalchemy.org/en/latest/core/pooling.html#sqlalchemy.pool.QueuePool
# http://docs.sqlalchemy.org/en/latest/core/pooling.html#sqlalchemy.pool.Pool.params
SQLALCHEMY_QUEUEPOOL = {
    'pool_size': 10,
    'max_overflow': 10,
    'timeout': 5,
    'recycle': 119,
}

DATABASES = {
    'default': {
        'ENGINE': 'django_conn_pool.mysql',
        'HOST': '127.0.0.1',
        'NAME': 'xxx',
        'USER': 'xxx',
        'PASSWORD': 'xxx',
        'PORT': 3306,
    },
    'other': {
        'ENGINE': 'django_conn_pool.mysql',
        'HOST': '127.0.0.1',
        'NAME': 'xxx',
        'USER': 'xxx',
        'PASSWORD': 'xxx',
        'PORT': 3306,
    },
}

测试

如果python manage.py runserver可以,现在可以使用负载测试实用程序Siege进行测试。

siege -r 2 -c 1000 -d 0 http://xxx  # siege --help

您可以将mysql进程列表计数与之前的进行比较,它应该可以工作。

顺便说一句,如果在请求过程中没有得到连接,那么应该得到一个sqlalchemy.exc.TimeoutError:异常。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java我想访问同一类的不同函数中的函数变量   创建字段/值哈希映射的java反射   java Velocity工具向后兼容性?   cmd JAVA运行时错误:发生JNI错误   java spring引导示例hateoas不工作   java为什么Android Studio和gradle可以使用不同的类路径进行单元测试?   java Selenium Firefox驱动程序初始化   java如何在jar中重新定位gradle依赖项的包   java为什么我的单线程hello world应用程序使用22个OS线程?   正则表达式替换Java字符串中的特殊字符   在任何派生类的构造函数之后运行方法的java   java从输入字符串中找出日期   带有libGdx(Java)音乐的安卓studio可以在Android模拟器上工作,但不能在桌面上工作   java我在getconnection的参数方面有错误吗?   java使用JFileChooser访问选定文件   java如何将Json解析为另一个活动   java使用Resources for html和rest server   java更新列表,列表内容来自循环中的方法   java如何在GLSL中读取完整范围的32位整数纹理