日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python django并发访问挂掉,解决django高并发时数据库连接量过大的问题(实现连接池的方法)...

發(fā)布時(shí)間:2025/4/5 python 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python django并发访问挂掉,解决django高并发时数据库连接量过大的问题(实现连接池的方法)... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Django默認(rèn)每訪問一次數(shù)據(jù)庫都會(huì)創(chuàng)建一個(gè)新的數(shù)據(jù)庫連接,執(zhí)行完數(shù)據(jù)庫操作后再關(guān)閉連接。這在高并發(fā)的場(chǎng)景下會(huì)導(dǎo)致連接數(shù)不斷增多,最終出現(xiàn)“too many connections”錯(cuò)誤。

如果我們使用gunicorn的gevent模式運(yùn)行項(xiàng)目,那么不能在項(xiàng)目中使用threading(多線程)模塊進(jìn)行數(shù)據(jù)庫操作。因?yàn)間event會(huì)給threading模塊動(dòng)態(tài)打補(bǔ)丁,這會(huì)導(dǎo)致數(shù)據(jù)庫連接無法復(fù)用,出現(xiàn)“too many connections”錯(cuò)誤。

要解決以上問題,我們需要實(shí)現(xiàn)一個(gè)數(shù)據(jù)庫的連接池。實(shí)現(xiàn)連接池的方法參考了https://yunsonbai.top/2017/07/02/gunicorn-gevent-django/,這里做了一些調(diào)優(yōu)。實(shí)現(xiàn)的步驟如下:

1. 在項(xiàng)目的settings.py中配置數(shù)據(jù)庫連接參數(shù),使用自定義的數(shù)據(jù)庫引擎

DATABASES = {

'default': {

'ENGINE': 'myproject.mysql', # 注意這里必須是.mysql結(jié)尾

'POOL_SIZE': 20, # 每個(gè)進(jìn)程的連接池的大小,總連接數(shù)=20*總進(jìn)程數(shù)

'NAME': 'test',

'USER': 'root',

'HOST': '127.0.0.1',

'PASSWORD': '******',

'STORAGE_ENGINE': 'INNODB',

'PORT': '3306',

'CHARSET': 'utf-8',

'CONN_MAX_AGE': 28790, # 比mysql默認(rèn)的wait_timeout小10秒

'OPTIONS': {

'init_command': 'SET default_storage_engine=INNODB',

}

}

}

2. 在項(xiàng)目中增加自定義的連接池模塊

以項(xiàng)目的根目錄為myproject為例,新建以下兩個(gè)文件:

myproject/mysql/__init__.py

myproject/mysql/base.py

這里的文件路徑mysql/base.py是固定搭配,文件夾、文件的名稱和層級(jí)關(guān)系不能變,否則會(huì)造成django及其插件導(dǎo)入數(shù)據(jù)庫引擎失敗,從而自動(dòng)使用默認(rèn)的數(shù)據(jù)庫引擎。

__init__.py是空文件,當(dāng)然也可以填充其他內(nèi)容。base.py的內(nèi)容如下:

# -*- coding: utf-8 -*-

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):

pool_size = self.settings_dict.get('POOL_SIZE') or 1

return ConnectPool.instance(conn_params, pool_size).get_connection()

def _close(self):

return None # 覆蓋掉原來的close方法,查詢結(jié)束后連接不會(huì)自動(dòng)關(guān)閉

class ConnectPool(object):

def __init__(self, conn_params, pool_size):

self.conn_params = conn_params

self.pool_size = pool_size

self.connects = []

# 實(shí)現(xiàn)連接池的單例

@staticmethod

def instance(conn_params, pool_size):

if not hasattr(ConnectPool, '_instance'):

ConnectPool._instance = ConnectPool(conn_params, pool_size)

return ConnectPool._instance

def get_connection(self):

if len(self.connects) < self.pool_size:

new_connect = Database.connect(**self.conn_params)

self.connects.append(new_connect)

return new_connect

index = random.randint(0, self.pool_size - 1) # 注意這里和range不一樣,要減1

try:

self.connects[index].ping()

except:

self.connects[index] = Database.connect(**self.conn_params)

return self.connects[index]

3. 調(diào)整mysql的配置

調(diào)整mysql的max_connections,使其大于項(xiàng)目的總連接數(shù)(連接池大小*服務(wù)進(jìn)程數(shù)),修改"/etc/mysql/my.cnf",在[mysqld]配置項(xiàng)下設(shè)置max_connections=1000,然后重啟mysql的服務(wù)。查看配置結(jié)果的sql:

SHOW VARIABLES LIKE "max_connections";

配置settings的CONN_MAX_AGE參數(shù),使其小于數(shù)據(jù)庫的wait_timeout配置,查看wait_timeout的sql:

SHOW GLOBAL VARIABLES LIKE "%wait%";

4. 驗(yàn)證結(jié)果

啟動(dòng)項(xiàng)目后訪問幾個(gè)會(huì)與數(shù)據(jù)庫交互的頁面,然后查看連接的數(shù)量,驗(yàn)證連接池的效果,查看連接數(shù)量的sql:

SHOW processlist;

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的python django并发访问挂掉,解决django高并发时数据库连接量过大的问题(实现连接池的方法)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。