fix: 禁用DB SSL连接,修复gunicorn preload_app导致的连接池损坏
This commit is contained in:
+71
-21
@@ -2,22 +2,55 @@
|
||||
数据库连接和用户认证
|
||||
"""
|
||||
import psycopg2
|
||||
from psycopg2 import pool
|
||||
from psycopg2.extras import RealDictCursor
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
from flask import session
|
||||
import functools
|
||||
from config import Config
|
||||
|
||||
_pool = None
|
||||
|
||||
|
||||
def init_db_pool():
|
||||
"""初始化数据库连接池(应用启动时调用一次)"""
|
||||
global _pool
|
||||
if _pool is not None:
|
||||
return
|
||||
try:
|
||||
_pool = pool.ThreadedConnectionPool(
|
||||
minconn=2,
|
||||
maxconn=20,
|
||||
host=Config.DB_HOST,
|
||||
port=Config.DB_PORT,
|
||||
database=Config.DB_NAME,
|
||||
user=Config.DB_USER,
|
||||
password=Config.DB_PASSWORD, sslmode='disable',
|
||||
)
|
||||
print(f"[DB] 连接池初始化成功 (min=2, max=20)")
|
||||
except Exception as e:
|
||||
print(f"[DB] 连接池初始化失败,降级为逐次建连: {e}")
|
||||
_pool = None
|
||||
|
||||
|
||||
def get_db():
|
||||
"""获取数据库连接"""
|
||||
"""从连接池获取数据库连接(用完必须调用 put_db(conn) 归还)"""
|
||||
global _pool
|
||||
if _pool is not None:
|
||||
try:
|
||||
conn = _pool.getconn()
|
||||
if conn and not conn.closed:
|
||||
conn.autocommit = False
|
||||
return conn
|
||||
except Exception as e:
|
||||
print(f"[DB] 连接池获取失败: {e}")
|
||||
try:
|
||||
conn = psycopg2.connect(
|
||||
host=Config.DB_HOST,
|
||||
port=Config.DB_PORT,
|
||||
database=Config.DB_NAME,
|
||||
user=Config.DB_USER,
|
||||
password=Config.DB_PASSWORD
|
||||
password=Config.DB_PASSWORD, sslmode="disable"
|
||||
)
|
||||
return conn
|
||||
except Exception as e:
|
||||
@@ -25,6 +58,23 @@ def get_db():
|
||||
return None
|
||||
|
||||
|
||||
def put_db(conn):
|
||||
"""归还连接到连接池"""
|
||||
if conn is None:
|
||||
return
|
||||
global _pool
|
||||
if _pool is not None:
|
||||
try:
|
||||
_pool.putconn(conn)
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def login_required(f):
|
||||
"""登录验证装饰器"""
|
||||
@functools.wraps(f)
|
||||
@@ -60,7 +110,7 @@ def db_get_available_cash(user_id):
|
||||
result = cur.fetchone()
|
||||
return float(result['available_cash'] or 0) if result else 0
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def db_update_available_cash(user_id, amount):
|
||||
@@ -78,7 +128,7 @@ def db_update_available_cash(user_id, amount):
|
||||
conn.rollback()
|
||||
return False, str(e)
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
# ========== 用户操作 ==========
|
||||
@@ -111,7 +161,7 @@ def create_user(email, password):
|
||||
conn.rollback()
|
||||
return None, str(e)
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def verify_user(email, password):
|
||||
@@ -131,7 +181,7 @@ def verify_user(email, password):
|
||||
|
||||
return {'id': user['id'], 'username': user.get('email') or user['username']}, None
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def change_user_password(user_id, old_password, new_password):
|
||||
@@ -158,7 +208,7 @@ def change_user_password(user_id, old_password, new_password):
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
# ========== 交易记录操作(数据库版) ==========
|
||||
@@ -181,7 +231,7 @@ def db_get_trades(user_id):
|
||||
""", (user_id,))
|
||||
return cur.fetchall()
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def db_get_trade(user_id, trade_id):
|
||||
@@ -199,7 +249,7 @@ def db_get_trade(user_id, trade_id):
|
||||
""", (trade_id, user_id))
|
||||
return cur.fetchone()
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def db_add_trade(user_id, data):
|
||||
@@ -239,7 +289,7 @@ def db_add_trade(user_id, data):
|
||||
conn.rollback()
|
||||
return None, str(e)
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def db_update_trade(user_id, trade_id, data):
|
||||
@@ -289,7 +339,7 @@ def db_update_trade(user_id, trade_id, data):
|
||||
conn.rollback()
|
||||
return None, str(e)
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def db_delete_trade(user_id, trade_id):
|
||||
@@ -304,7 +354,7 @@ def db_delete_trade(user_id, trade_id):
|
||||
conn.commit()
|
||||
return cur.rowcount > 0
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
# ========== 关注列表操作(数据库版) ==========
|
||||
@@ -325,7 +375,7 @@ def db_get_watchlist(user_id):
|
||||
""", (user_id,))
|
||||
return cur.fetchall()
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def db_add_to_watchlist(user_id, code, name):
|
||||
@@ -348,7 +398,7 @@ def db_add_to_watchlist(user_id, code, name):
|
||||
conn.rollback()
|
||||
return None, str(e)
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def db_remove_from_watchlist(user_id, code):
|
||||
@@ -363,7 +413,7 @@ def db_remove_from_watchlist(user_id, code):
|
||||
conn.commit()
|
||||
return db_get_watchlist(user_id)
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
# ========== 分析缓存操作(数据库版) ==========
|
||||
@@ -389,7 +439,7 @@ def db_get_alerts_cache(user_id):
|
||||
}
|
||||
return {'alerts': [], 'lastUpdate': None}
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def db_save_alerts_cache(user_id, alerts):
|
||||
@@ -415,7 +465,7 @@ def db_save_alerts_cache(user_id, alerts):
|
||||
print(f"保存分析缓存失败: {e}")
|
||||
return False
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
# ========== 基本面数据操作(数据库版) ==========
|
||||
@@ -438,7 +488,7 @@ def db_get_fundamental(code):
|
||||
""", (code, date.today()))
|
||||
return cur.fetchone()
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def db_save_fundamental(code, data):
|
||||
@@ -497,7 +547,7 @@ def db_save_fundamental(code, data):
|
||||
print(f"保存基本面数据失败: {e}")
|
||||
return False
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
# ========== 资金流向历史数据操作(数据库版) ==========
|
||||
@@ -526,7 +576,7 @@ def db_get_fund_flow_history(code):
|
||||
|
||||
return [dict(row) for row in rows], latest_date
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
|
||||
def db_save_fund_flow_history(code, records):
|
||||
@@ -584,4 +634,4 @@ def db_save_fund_flow_history(code, records):
|
||||
print(f"保存资金流向历史失败: {e}")
|
||||
return False
|
||||
finally:
|
||||
conn.close()
|
||||
put_db(conn)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
"""Gunicorn 生产环境配置"""
|
||||
import multiprocessing
|
||||
|
||||
bind = "0.0.0.0:3333"
|
||||
workers = min(multiprocessing.cpu_count() * 2 + 1, 4)
|
||||
worker_class = "gthread"
|
||||
threads = 4
|
||||
timeout = 120
|
||||
keepalive = 5
|
||||
max_requests = 1000
|
||||
max_requests_jitter = 50
|
||||
accesslog = "-"
|
||||
errorlog = "-"
|
||||
loglevel = "info"
|
||||
preload_app = False
|
||||
Reference in New Issue
Block a user