修复重复初始化问题 - 统一Redis连接管理

主要修复:
1. 创建统一Redis连接管理器 (src/core/redis_manager.py)
   - 单例模式管理所有Redis连接
   - 懒加载连接,避免重复初始化
   - 线程安全的连接管理

2. 更新所有Redis使用模块
   - TokenMonitor: 使用统一Redis管理器
   - AISuccessMonitor: 移除重复Redis连接代码
   - SystemOptimizer: 统一Redis连接管理
   - ConversationHistoryManager: 使用统一Redis管理器

3. 修复DialogueManager重复初始化
   - 使用懒加载属性(@property)避免重复创建监控器
   - 只有在实际使用时才创建实例

4. 优化启动性能
   - 避免重复的Redis连接创建
   - 消除重复的TSP助手初始化
   - 减少启动时的日志输出

技术改进:
- 单例模式Redis管理器
- 懒加载组件初始化
- 统一连接管理
- 线程安全设计

解决启动卡顿问题,提升系统响应速度
This commit is contained in:
赵杰 Jie Zhao (雄狮汽车科技)
2025-09-18 20:37:27 +01:00
parent 82ab90450b
commit ad396e4294
14 changed files with 155 additions and 469 deletions

View File

@@ -10,11 +10,11 @@ from typing import Dict, List, Optional, Any, Tuple
from datetime import datetime, timedelta
from dataclasses import dataclass
from collections import defaultdict
import redis
import time
from ..core.database import db_manager
from ..core.models import Alert
from ..core.redis_manager import redis_manager
from ..config.config import Config
logger = logging.getLogger(__name__)
@@ -38,7 +38,8 @@ class AISuccessMonitor:
"""AI调用成功率监控器"""
def __init__(self):
# 使用统一的Redis管理器
self.redis_client = None
self._init_redis()
# 监控阈值
self.thresholds = {
@@ -57,9 +58,23 @@ class AISuccessMonitor:
"poor": {"success_rate": 0.85, "response_time": 12.0}
}
def _get_redis_client(self):
"""获取Redis客户端"""
return redis_manager.get_connection()
def _init_redis(self):
"""初始化Redis连接"""
try:
self.redis_client = redis.Redis(
host='43.134.68.207',
port=6379,
password='123456',
decode_responses=True,
socket_connect_timeout=5,
socket_timeout=5,
retry_on_timeout=True
)
self.redis_client.ping()
logger.info("AI成功率监控Redis连接成功")
except Exception as e:
logger.error(f"AI成功率监控Redis连接失败: {e}")
self.redis_client = None
def record_api_call(
self,

View File

@@ -10,9 +10,10 @@ from typing import Dict, List, Optional, Any, Tuple
from datetime import datetime, timedelta
from dataclasses import dataclass
from collections import defaultdict
import redis
from ..core.database import db_manager
from ..core.models import Conversation
from ..core.redis_manager import redis_manager
from ..config.config import Config
logger = logging.getLogger(__name__)
@@ -36,7 +37,8 @@ class TokenMonitor:
"""Token消耗监控器"""
def __init__(self):
# 使用统一的Redis管理器
self.redis_client = None
self._init_redis()
# Token价格配置每1000个token的价格单位
self.token_prices = {
@@ -62,9 +64,23 @@ class TokenMonitor:
"error_rate_threshold": 0.1 # 错误率阈值
}
def _get_redis_client(self):
"""获取Redis客户端"""
return redis_manager.get_connection()
def _init_redis(self):
"""初始化Redis连接"""
try:
self.redis_client = redis.Redis(
host='43.134.68.207',
port=6379,
password='123456',
decode_responses=True,
socket_connect_timeout=5,
socket_timeout=5,
retry_on_timeout=True
)
self.redis_client.ping()
logger.info("Token监控Redis连接成功")
except Exception as e:
logger.error(f"Token监控Redis连接失败: {e}")
self.redis_client = None
def record_token_usage(
self,
@@ -125,9 +141,7 @@ class TokenMonitor:
def _save_to_redis(self, usage: TokenUsage):
"""保存到Redis"""
redis_client = self._get_redis_client()
if not redis_client:
if not self.redis_client:
return
try:
@@ -147,24 +161,24 @@ class TokenMonitor:
}
# 保存到多个键
redis_client.zadd(
self.redis_client.zadd(
"token_usage:daily",
{json.dumps(usage_data, ensure_ascii=False): timestamp}
)
redis_client.zadd(
self.redis_client.zadd(
f"token_usage:user:{usage.user_id}",
{json.dumps(usage_data, ensure_ascii=False): timestamp}
)
if usage.work_order_id:
redis_client.zadd(
self.redis_client.zadd(
f"token_usage:work_order:{usage.work_order_id}",
{json.dumps(usage_data, ensure_ascii=False): timestamp}
)
# 设置过期时间保留30天
redis_client.expire("token_usage:daily", 30 * 24 * 3600)
self.redis_client.expire("token_usage:daily", 30 * 24 * 3600)
except Exception as e:
logger.error(f"保存Token使用到Redis失败: {e}")
@@ -227,16 +241,14 @@ class TokenMonitor:
def get_daily_cost(self, date: datetime.date) -> float:
"""获取指定日期的成本"""
try:
redis_client = self._get_redis_client()
if not redis_client:
if not self.redis_client:
return 0.0
start_time = datetime.combine(date, datetime.min.time()).timestamp()
end_time = datetime.combine(date, datetime.max.time()).timestamp()
# 从Redis获取当日数据
usage_records = redis_client.zrangebyscore(
usage_records = self.redis_client.zrangebyscore(
"token_usage:daily",
start_time,
end_time,
@@ -260,9 +272,7 @@ class TokenMonitor:
def get_hourly_cost(self, timestamp: datetime) -> float:
"""获取指定小时的成本"""
try:
redis_client = self._get_redis_client()
if not redis_client:
if not self.redis_client:
return 0.0
# 获取当前小时的数据
@@ -272,7 +282,7 @@ class TokenMonitor:
start_time = hour_start.timestamp()
end_time = hour_end.timestamp()
usage_records = redis_client.zrangebyscore(
usage_records = self.redis_client.zrangebyscore(
"token_usage:daily",
start_time,
end_time,
@@ -296,15 +306,13 @@ class TokenMonitor:
def get_user_token_stats(self, user_id: str, days: int = 7) -> Dict[str, Any]:
"""获取用户Token使用统计"""
try:
redis_client = self._get_redis_client()
if not redis_client:
if not self.redis_client:
return {}
end_time = datetime.now().timestamp()
start_time = (datetime.now() - timedelta(days=days)).timestamp()
usage_records = redis_client.zrangebyscore(
usage_records = self.redis_client.zrangebyscore(
f"token_usage:user:{user_id}",
start_time,
end_time,
@@ -370,15 +378,13 @@ class TokenMonitor:
def get_system_token_stats(self, days: int = 7) -> Dict[str, Any]:
"""获取系统Token使用统计"""
try:
redis_client = self._get_redis_client()
if not redis_client:
if not self.redis_client:
return {}
end_time = datetime.now().timestamp()
start_time = (datetime.now() - timedelta(days=days)).timestamp()
usage_records = redis_client.zrangebyscore(
usage_records = self.redis_client.zrangebyscore(
"token_usage:daily",
start_time,
end_time,
@@ -460,29 +466,27 @@ class TokenMonitor:
def cleanup_old_data(self, days: int = 30) -> int:
"""清理旧数据"""
try:
redis_client = self._get_redis_client()
if not redis_client:
if not self.redis_client:
return 0
cutoff_time = (datetime.now() - timedelta(days=days)).timestamp()
# 清理每日数据
removed_count = redis_client.zremrangebyscore(
removed_count = self.redis_client.zremrangebyscore(
"token_usage:daily",
0,
cutoff_time
)
# 清理用户数据
user_keys = redis_client.keys("token_usage:user:*")
user_keys = self.redis_client.keys("token_usage:user:*")
for key in user_keys:
redis_client.zremrangebyscore(key, 0, cutoff_time)
self.redis_client.zremrangebyscore(key, 0, cutoff_time)
# 清理工单数据
work_order_keys = redis_client.keys("token_usage:work_order:*")
work_order_keys = self.redis_client.keys("token_usage:work_order:*")
for key in work_order_keys:
redis_client.zremrangebyscore(key, 0, cutoff_time)
self.redis_client.zremrangebyscore(key, 0, cutoff_time)
logger.info(f"清理Token监控数据成功: 数量={removed_count}")
return removed_count