## 主要更改 ### 1. 数据库表结构增强 - **t_device_message_v2**: 新增7个关键字段 - priority_level: 优先级数值(1-5) - channels: 分发渠道JSON - require_ack: 是否需要确认 - metadata: 扩展元数据JSON - target_count: 目标用户总数 - version: 乐观锁版本号 - **t_device_message_detail_v2**: 新增8个关键字段 - distribution_id: 分发唯一ID - device_sn: 设备序列号 - user_id: 用户ID(核心查询字段) - response_duration: 响应耗时 - delivery_details: 分发详情JSON - client_info: 客户端信息JSON - location_info: 位置信息JSON - last_retry_time: 最后重试时间 ### 2. 索引优化重构 (基于user_id) - 删除原有device_sn相关索引 - 新建5个user_id高性能复合索引: - idx_customer_user_time: 客户+用户+时间 - idx_customer_user_status: 客户+用户+状态 - idx_customer_user_type: 客户+用户+类型 - idx_user_org_priority: 用户+组织+优先级 - idx_user_status_time: 用户+状态+时间 - detail表新建4个user_id相关索引: - uk_message_user_target: 唯一约束 - idx_customer_user_status: 客户+用户+状态 - idx_user_channel_time: 用户+渠道+时间 - idx_user_delivery_status: 用户+分发状态 ### 3. 数据迁移和初始化 - 自动生成distribution_id - 根据urgency设置priority_level - 初始化默认channels配置 - 保持现有数据完整性 ### 4. 性能提升预期 - 用户消息查询: 预计10-20倍性能提升 - 确认状态查询: 支持快速人员清单检索 - 存储空间: JSON字段替代冗余VARCHAR - 查询覆盖: 所有user_id查询都能命中索引 ### 5. 文档和脚本 - 完整的V2优化SQL脚本 - 消息机制设计文档 - 数据库备份(22MB) - 性能验证查询 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
254 lines
8.9 KiB
Markdown
254 lines
8.9 KiB
Markdown
# 简洁告警系统优化方案
|
|
|
|
## 📋 基于现有代码的简单改进
|
|
|
|
基于对 ljwx-bigscreen 现有 `generate_alerts` 函数的分析,提供最简洁有效的优化方案。
|
|
|
|
## 🔍 现状分析
|
|
|
|
### 当前 generate_alerts 函数问题:
|
|
1. **规则查询无过滤** - 每次都加载所有告警规则,未按数据类型过滤
|
|
2. **重复设备信息查询** - 每条规则都可能重复查询相同设备信息
|
|
3. **缺乏通知渠道处理** - 触发告警后没有自动通知机制
|
|
|
|
### 现有优势:
|
|
- 已有 Redis 缓存机制
|
|
- 已有规则预编译逻辑
|
|
- 数据库查询已优化
|
|
|
|
## 🚀 三个简单优化
|
|
|
|
### 1. 规则按数据类型过滤 (最简单改进)
|
|
|
|
**问题**: 当前所有规则都被加载,浪费处理时间
|
|
|
|
**解决**: 在 `generate_alerts` 函数中按 physical_sign 过滤规则
|
|
|
|
```python
|
|
def generate_alerts(data, health_data_id):
|
|
# 现有代码...获取所有规则
|
|
|
|
# 🚀 新增: 从数据中提取当前的 physical_sign 类型
|
|
current_physical_signs = set()
|
|
for key in data.keys():
|
|
if key in ['heartRate', 'bloodOxygen', 'temperature', 'pressureHigh', 'pressureLow',
|
|
'stress', 'step', 'calorie', 'distance', 'sleep']:
|
|
# 将前端字段映射到数据库字段
|
|
sign_mapping = {
|
|
'heartRate': 'heart_rate',
|
|
'bloodOxygen': 'blood_oxygen',
|
|
'pressureHigh': 'bloodPressure',
|
|
'pressureLow': 'bloodPressure',
|
|
'step': 'steps'
|
|
}
|
|
current_physical_signs.add(sign_mapping.get(key, key))
|
|
|
|
# 🚀 过滤规则: 只处理当前数据相关的规则
|
|
filtered_rules = {}
|
|
for rule_id, rule in alert_rules_dict.items():
|
|
physical_sign = rule.get('physical_sign')
|
|
if physical_sign in current_physical_signs:
|
|
filtered_rules[rule_id] = rule
|
|
|
|
print(f"📋 规则过滤: {len(alert_rules_dict)} -> {len(filtered_rules)} 条")
|
|
|
|
# 后续处理使用 filtered_rules 替代 alert_rules_dict
|
|
alert_rules_dict = filtered_rules
|
|
|
|
# 现有代码继续...
|
|
```
|
|
|
|
### 2. 设备信息缓存 (性能提升)
|
|
|
|
**问题**: `get_device_user_org_info` 在每个规则匹配时都可能被调用
|
|
|
|
**解决**: 在函数开头一次性获取并缓存
|
|
|
|
```python
|
|
def generate_alerts(data, health_data_id):
|
|
# 现有代码...
|
|
|
|
# 🚀 新增: 提前获取设备信息并缓存
|
|
device_sn = data.get('deviceSn')
|
|
device_info_cache = None
|
|
|
|
if device_sn:
|
|
try:
|
|
device_info_cache = get_device_user_org_info(device_sn)
|
|
print(f"📱 设备信息已缓存: {device_sn}")
|
|
except Exception as e:
|
|
print(f"⚠️ 获取设备信息失败: {e}")
|
|
|
|
# 遍历规则时使用缓存的设备信息
|
|
for rule_id, rule in filtered_rules.items():
|
|
# 现有规则匹配逻辑...
|
|
|
|
# 当需要设备信息时,使用缓存
|
|
if device_info_cache:
|
|
user_id = device_info_cache.get('user_id')
|
|
org_id = device_info_cache.get('org_id')
|
|
user_name = device_info_cache.get('user_name', 'Unknown')
|
|
# 使用缓存的信息而不是重复查询
|
|
```
|
|
|
|
### 3. 简单通知渠道处理
|
|
|
|
**问题**: 告警生成后没有自动通知机制
|
|
|
|
**解决**: 在现有告警保存后添加简单的通知处理
|
|
|
|
```python
|
|
def send_simple_notification(alert_info, device_info):
|
|
"""简单的通知发送函数"""
|
|
try:
|
|
user_name = device_info.get('user_name', 'Unknown')
|
|
org_name = device_info.get('org_name', 'Unknown')
|
|
|
|
# 构建通知消息
|
|
message = f"【健康告警】{user_name}({org_name}) - {alert_info.get('alert_type', '')}: {alert_info.get('alert_desc', '')}"
|
|
|
|
# 如果有微信配置,发送微信通知
|
|
if hasattr(current_app, 'config') and current_app.config.get('WECHAT_ENABLED'):
|
|
openid = device_info.get('openid') # 需要在设备信息中包含openid
|
|
if openid:
|
|
send_wechat_alert(
|
|
alert_type=alert_info.get('alert_type'),
|
|
user_openid=openid,
|
|
user_name=user_name,
|
|
severity_level=alert_info.get('severity_level', 'medium')
|
|
)
|
|
print(f"📱 微信通知已发送: {user_name}")
|
|
|
|
# 记录通知日志
|
|
print(f"🔔 告警通知: {message}")
|
|
|
|
except Exception as e:
|
|
print(f"⚠️ 通知发送失败: {e}")
|
|
|
|
def generate_alerts(data, health_data_id):
|
|
# 现有代码...处理规则匹配
|
|
|
|
# 在保存告警后添加通知
|
|
if alert_triggered: # 当有告警触发时
|
|
# 现有保存逻辑...
|
|
|
|
# 🚀 新增: 发送通知
|
|
try:
|
|
send_simple_notification(alert_info, device_info_cache)
|
|
except Exception as notify_error:
|
|
print(f"通知发送异常: {notify_error}")
|
|
```
|
|
|
|
## 📝 完整集成代码
|
|
|
|
将以上三个改进集成到现有 `generate_alerts` 函数:
|
|
|
|
```python
|
|
def generate_alerts(data, health_data_id):
|
|
start_time = time.time()
|
|
try:
|
|
print(f"🔍 generate_alerts started with data keys: {list(data.keys()) if data else 'None'}")
|
|
|
|
# 现有代码: 获取告警规则...
|
|
customer_id = data.get('customer_id') or data.get('customerId')
|
|
alert_rules_dict = {}
|
|
cache_hit = False
|
|
|
|
# [保留现有的规则获取逻辑]
|
|
# ...
|
|
|
|
# 🚀 优化1: 规则按数据类型过滤
|
|
current_physical_signs = set()
|
|
sign_mapping = {
|
|
'heartRate': 'heart_rate', 'bloodOxygen': 'blood_oxygen',
|
|
'pressureHigh': 'bloodPressure', 'pressureLow': 'bloodPressure',
|
|
'step': 'steps', 'calorie': 'calories', 'distance': 'distance',
|
|
'temperature': 'temperature', 'stress': 'stress', 'sleep': 'sleep'
|
|
}
|
|
|
|
for key in data.keys():
|
|
if key in sign_mapping:
|
|
current_physical_signs.add(sign_mapping[key])
|
|
|
|
# 过滤规则
|
|
filtered_rules = {rid: rule for rid, rule in alert_rules_dict.items()
|
|
if rule.get('physical_sign') in current_physical_signs}
|
|
|
|
print(f"📋 规则过滤: {len(alert_rules_dict)} -> {len(filtered_rules)}")
|
|
|
|
# 🚀 优化2: 设备信息预获取
|
|
device_sn = data.get('deviceSn')
|
|
device_info_cache = None
|
|
if device_sn:
|
|
try:
|
|
device_info_cache = get_device_user_org_info(device_sn)
|
|
except Exception as e:
|
|
print(f"⚠️ 设备信息获取失败: {e}")
|
|
|
|
# 现有规则匹配逻辑,使用 filtered_rules 和 device_info_cache
|
|
abnormal_counts = {}
|
|
alerts_generated = 0
|
|
|
|
for rule_id, rule in filtered_rules.items():
|
|
# [保留现有的规则匹配逻辑]
|
|
# 使用 device_info_cache 替代重复查询
|
|
|
|
# 当触发告警时
|
|
if alert_condition_met: # 现有的触发条件判断
|
|
# [保留现有的告警创建和保存逻辑]
|
|
|
|
# 🚀 优化3: 简单通知处理
|
|
if device_info_cache:
|
|
try:
|
|
send_simple_notification(alert_info, device_info_cache)
|
|
except Exception as notify_error:
|
|
print(f"通知异常: {notify_error}")
|
|
|
|
alerts_generated += 1
|
|
|
|
processing_time = round((time.time() - start_time) * 1000, 2)
|
|
print(f"⏱️ generate_alerts 完成: 处理{len(filtered_rules)}条规则, 生成{alerts_generated}个告警, 耗时{processing_time}ms")
|
|
|
|
return alerts_generated
|
|
|
|
except Exception as e:
|
|
print(f"❌ generate_alerts 异常: {e}")
|
|
return 0
|
|
```
|
|
|
|
## 📊 预期效果
|
|
|
|
### 性能提升
|
|
- **规则过滤**: 减少 60-80% 不必要的规则处理
|
|
- **设备查询**: 消除重复查询,节省 50-70% 数据库调用
|
|
- **响应时间**: 整体处理时间减少 40-60%
|
|
|
|
### 功能增强
|
|
- **自动通知**: 告警触发后自动发送通知
|
|
- **日志完善**: 更清晰的处理过程日志
|
|
- **错误处理**: 更好的异常处理机制
|
|
|
|
## 🔧 部署建议
|
|
|
|
### 实施步骤
|
|
1. **第一步**: 仅实施规则过滤优化 (风险最小)
|
|
2. **第二步**: 添加设备信息缓存 (性能提升明显)
|
|
3. **第三步**: 集成通知处理 (功能增强)
|
|
|
|
### 配置要求
|
|
```python
|
|
# config.py 中添加
|
|
WECHAT_ENABLED = True # 是否启用微信通知
|
|
NOTIFICATION_ENABLED = True # 是否启用通知功能
|
|
```
|
|
|
|
### 监控要点
|
|
- 规则过滤效率: 过滤前后规则数量
|
|
- 设备查询次数: 确认缓存生效
|
|
- 通知成功率: 监控通知发送情况
|
|
|
|
这个方案基于现有代码架构,改动最小,风险可控,可以立即实施并看到效果。
|
|
|
|
---
|
|
*简化版本: v1.0*
|
|
*基于现有代码: ljwx-bigscreen/alert.py* |