使用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]
发表评论
共 0 条评论
暂无评论