随心一记

一二三四五,上山打老鼠


  • 首页

  • 归档

  • 标签
ywcsb

ywcsb

游戏可以不玩,小说不能不看。

153 日志
3 分类
42 标签
RSS
GitHub 知乎 随心一记
Links
  • 随心一记
  • 追梦人物的
  • MSDN

解决gunicorn+gevent+django数据库高连接数问题

发表于 2019-09-17 | 阅读 930 | 分类于 Python |

使用gunicorn+gevent+django+CONN_MAX_AGE会导致数据库连接数飙升,直至占满。如果一定要利用协程的方式启动,该怎么解决这个问题呢?看了一下django源码,找到了问题的根源,写了一下解决办法。

1. 在项目的settings.py中配置数据库连接参数,使用自定义的数据库引擎
DATABASES = {
    'default': {
        'ENGINE': 'blog.mysql',  # 注意这里必须是.mysql结尾
        'NAME': 'myblog',
        'USER': 'myblog',
        'PASSWORD': '******',
        'HOST': '10.20.3.4',
        'PORT': '3306',
        'CONN_MAX_AGE': 3600, # 比mysql默认的wait_timeout小10秒
        'OPTIONS': {
            'autocommit': True,
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}
2. 在项目中增加自定义的mysql连接池模块

在settings.py目录下新建以下两个文件

mysql/__init__.py
mysql/base.py

这里的文件路径mysql/base.py是固定搭配,文件夹、文件的名称和层级关系不能变,否则会造成django及其插件导入数据库引擎失败,从而自动使用默认的数据库引擎。

init.py是空文件,当然也可以填充其他内容。base.py的内容如下:

import random
from django.core.exceptions import ImproperlyConfigured

try:
    import MySQLdb as Database
except ImportError as err:
    raise ImproperlyConfigured(
        'Error loading MySQLdb module.\n'
        'Did you install mysqlclient?'
    ) from err

from django.db.backends.mysql.base import *
from django.db.backends.mysql.base import DatabaseWrapper as _DatabaseWrapper


class DatabaseWrapper(_DatabaseWrapper):
    def get_new_connection(self, conn_params):
        return ConnectPool.instance(conn_params).get_connection()

    def _close(self):
        return None  # 假关闭


class ConnectPool(object):
    def __init__(self, conn_params):
        self.conn_params = conn_params
        self.n = 5
        self.connects = []

    # 未实现单例,实现连接池
    @staticmethod
    def instance(conn_params):
        if not hasattr(ConnectPool, '_instance'):
            ConnectPool._instance = ConnectPool(conn_params)
        return ConnectPool._instance

    def get_connection(self):
        c = None
        if len(self.connects) <= self.n:
            c = Database.connect(**self.conn_params)
            self.connects.append(c)
        if c:
            return c
        index = random.randint(0, self.n)
        try:
            self.connects[index].ping()
        except Exception as e:
            self.connects[index] = Database.connect(**self.conn_params)
        return self.connects[index]
觉得不错,支持一下!
geerniya WeChat Pay

微信打赏

geerniya Alipay

支付宝打赏

# Nginx # MySQL # Python # Django
Xadmin 使用form_layout自定义编辑页面布局
Linux下离线安装Docker最新版本

发表评论

共 0 条评论

    暂无评论
© 2018 - 2022 ywcsb
冀ICP备17022045号-1
Supported by 腾讯云