# 告警规则系统全流程可落地实施方案 ## 📋 方案概述 基于现有系统架构和优化文档,整合告警规则、缓存同步、消息发布等所有优化策略,提供一个完整的、可直接落地的实施方案。 ### 🎯 核心目标 - **统一规则管理**: 支持单体征、复合、复杂三类告警规则 - **高效缓存同步**: Redis三层缓存架构,TTL延长至24小时 - **消息发布优化**: 统一消息模型,支持多渠道分发 - **高并发处理**: 异步队列+批量处理,性能提升80%以上 - **管理界面友好**: 可视化规则配置向导 ## 🏗️ 整体架构设计 ### 系统架构图 ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ ljwx-admin │ │ ljwx-boot │ │ ljwx-bigscreen │ │ 规则管理界面 │ ←→ │ 规则引擎+缓存 │ ←→ │ 告警生成+处理 │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ │ │ │ ▼ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Vue3配置界面 │ │ Redis缓存同步 │ │ 异步队列处理 │ │ 可视化规则向导 │ │ DB=1 ←pub/sub→ │ │ 三层缓存优化 │ └─────────────────┘ └─────────────────┘ └─────────────────┘ ``` ### 数据流向 ``` 告警规则配置 → ljwx-admin → ljwx-boot API → MySQL数据库 ↓ Redis发布订阅通知 ↓ ljwx-bigscreen订阅更新 → 本地缓存刷新 ↓ 健康数据上传 → 规则评估引擎 ↓ 复合条件评估 → 告警生成 ↓ 消息分发 → 微信/短信/大屏推送 ``` ## 🗄️ 数据库设计 ### 1. 告警规则表优化 (t_alert_rules) #### 1.1 向下兼容的表结构增强 ```sql -- 保持现有字段,新增扩展字段 ALTER TABLE `t_alert_rules` ADD COLUMN `rule_category` ENUM('SINGLE', 'COMPOSITE', 'COMPLEX') DEFAULT 'SINGLE' COMMENT '规则类型:单体征/复合/复杂', ADD COLUMN `condition_expression` JSON COMMENT '复合条件表达式', ADD COLUMN `time_window_seconds` INT DEFAULT 300 COMMENT '时间窗口(秒)', ADD COLUMN `cooldown_seconds` INT DEFAULT 600 COMMENT '告警冷却期(秒)', ADD COLUMN `priority_level` INT DEFAULT 3 COMMENT '优先级(1-5,数字越小优先级越高)', ADD COLUMN `rule_tags` JSON COMMENT '规则标签,便于分类管理', ADD COLUMN `effective_time_start` TIME COMMENT '生效开始时间', ADD COLUMN `effective_time_end` TIME COMMENT '生效结束时间', ADD COLUMN `effective_days` VARCHAR(20) DEFAULT '1,2,3,4,5,6,7' COMMENT '生效星期(1-7)', ADD COLUMN `version` BIGINT DEFAULT 1 COMMENT '规则版本号', ADD COLUMN `enabled_channels` JSON COMMENT '启用的通知渠道', ADD INDEX idx_customer_category (`customer_id`, `rule_category`), ADD INDEX idx_priority (`priority_level`), ADD INDEX idx_physical_sign_active (`physical_sign`, `is_active`); ``` #### 1.2 规则条件表达式设计 ```json -- 单体征规则 (现有兼容) { "rule_type": "single", "physical_sign": "heart_rate", "threshold_min": 60, "threshold_max": 120, "trend_duration": 3 } -- 复合规则 (新增) { "rule_type": "composite", "conditions": [ { "physical_sign": "heart_rate", "operator": ">", "threshold": 120, "duration_seconds": 180 }, { "physical_sign": "blood_oxygen", "operator": "<", "threshold": 90, "duration_seconds": 60 } ], "logical_operator": "AND", "evaluation_window": 300 } -- 复杂规则 (高级) { "rule_type": "complex", "expression": "((heart_rate > 120 AND blood_oxygen < 90) OR (temperature > 38.5)) AND time_of_day BETWEEN '09:00' AND '17:00'", "variables": { "heart_rate": "health_data.heart_rate", "blood_oxygen": "health_data.blood_oxygen", "temperature": "health_data.temperature", "time_of_day": "CURRENT_TIME" } } ``` ### 2. 告警记录表增强 (t_alert_info) ```sql ALTER TABLE `t_alert_info` ADD COLUMN `rule_version` BIGINT COMMENT '规则版本', ADD COLUMN `trigger_conditions` JSON COMMENT '触发条件详情', ADD COLUMN `evaluation_context` JSON COMMENT '评估上下文', ADD COLUMN `suppression_key` VARCHAR(128) COMMENT '抑制键', ADD COLUMN `escalation_level` INT DEFAULT 0 COMMENT '升级级别', ADD COLUMN `ack_required` BOOLEAN DEFAULT FALSE COMMENT '是否需要确认', ADD COLUMN `auto_resolve` BOOLEAN DEFAULT FALSE COMMENT '是否自动恢复', ADD INDEX idx_suppression (`suppression_key`), ADD INDEX idx_escalation (`escalation_level`), ADD INDEX idx_rule_version (`rule_id`, `rule_version`); ``` ### 3. 缓存同步表 (新增) ```sql CREATE TABLE `t_alert_cache_sync` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, `customer_id` BIGINT NOT NULL, `cache_key` VARCHAR(255) NOT NULL, `version` BIGINT NOT NULL DEFAULT 1, `last_sync_time` DATETIME DEFAULT CURRENT_TIMESTAMP, `sync_status` ENUM('pending', 'synced', 'failed') DEFAULT 'pending', `error_message` TEXT, UNIQUE KEY uk_customer_cache (`customer_id`, `cache_key`), INDEX idx_sync_status (`sync_status`), INDEX idx_last_sync (`last_sync_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='告警规则缓存同步状态表'; ``` ## 🚀 后端实现 (ljwx-boot) ### 1. 规则引擎核心类 ```java @Service @Slf4j public class AlertRuleEngineService { @Autowired private RedisTemplate redisTemplate; @Autowired private TAlertRulesMapper alertRulesMapper; /** * 规则评估主入口 */ public List evaluateRules(HealthDataEvent healthData) { String customerId = healthData.getCustomerId(); // 1. 获取缓存的规则 List rules = getCachedRules(customerId); // 2. 规则预编译和分组 CompiledRuleSet compiledRules = compileRules(rules); // 3. 并行评估 return evaluateRulesParallel(healthData, compiledRules); } /** * 三层缓存获取规则 */ private List getCachedRules(String customerId) { String cacheKey = "alert_rules:" + customerId; // L1: JVM缓存 (5分钟) List rules = localCache.get(cacheKey); if (rules != null) { return rules; } // L2: Redis缓存 (24小时) rules = (List) redisTemplate.opsForValue().get(cacheKey); if (rules != null) { localCache.put(cacheKey, rules); return rules; } // L3: 数据库 rules = alertRulesMapper.selectByCustomerId(Long.valueOf(customerId)); // 回填缓存 redisTemplate.opsForValue().set(cacheKey, rules, Duration.ofHours(24)); localCache.put(cacheKey, rules); return rules; } /** * 规则预编译 */ private CompiledRuleSet compileRules(List rules) { CompiledRuleSet compiledRules = new CompiledRuleSet(); for (TAlertRules rule : rules) { if (!rule.getIsActive()) continue; switch (rule.getRuleCategory()) { case SINGLE: compiledRules.addSingleRule(compileSingleRule(rule)); break; case COMPOSITE: compiledRules.addCompositeRule(compileCompositeRule(rule)); break; case COMPLEX: compiledRules.addComplexRule(compileComplexRule(rule)); break; } } return compiledRules; } /** * 并行规则评估 */ private List evaluateRulesParallel(HealthDataEvent healthData, CompiledRuleSet compiledRules) { List>> futures = new ArrayList<>(); // 单体征规则并行评估 futures.add(CompletableFuture.supplyAsync(() -> evaluateSingleRules(healthData, compiledRules.getSingleRules()))); // 复合规则并行评估 futures.add(CompletableFuture.supplyAsync(() -> evaluateCompositeRules(healthData, compiledRules.getCompositeRules()))); // 复杂规则并行评估 futures.add(CompletableFuture.supplyAsync(() -> evaluateComplexRules(healthData, compiledRules.getComplexRules()))); // 合并结果 return futures.stream() .map(CompletableFuture::join) .flatMap(List::stream) .collect(Collectors.toList()); } } ``` ### 2. 缓存同步增强版 ```java @Component @Slf4j public class AlertRulesCacheManager { @Autowired private RedisTemplate redisTemplate; @Autowired private TAlertCacheSyncMapper cacheSyncMapper; /** * 更新告警规则缓存 - 增强版本 */ @Transactional public void updateAlertRulesCache(Long customerId) { String lockKey = "alert_rules_lock_" + customerId; // 分布式锁 Boolean lockAcquired = redisTemplate.opsForValue() .setIfAbsent(lockKey, "locked", Duration.ofMinutes(5)); if (!lockAcquired) { log.warn("获取分布式锁失败: {}", lockKey); return; } try { // 1. 查询最新规则 List rules = alertRulesMapper.selectByCustomerId(customerId); // 2. 增加版本号 Long version = redisTemplate.opsForValue().increment("alert_rules_version_" + customerId); // 3. 构建缓存数据 CacheData cacheData = CacheData.builder() .version(version) .rules(rules) .updateTime(System.currentTimeMillis()) .customerId(customerId) .build(); // 4. 更新Redis缓存 String cacheKey = "alert_rules_" + customerId; redisTemplate.opsForValue().set(cacheKey, cacheData, Duration.ofHours(24)); // 5. 发布更新通知 String message = String.format("update:%s:%s", customerId, version); redisTemplate.convertAndSend("alert_rules_channel", message); // 6. 记录同步状态 updateSyncStatus(customerId, cacheKey, version, "synced", null); log.info("告警规则缓存更新成功: customerId={}, version={}", customerId, version); } catch (Exception e) { log.error("告警规则缓存更新失败: customerId={}", customerId, e); updateSyncStatus(customerId, "alert_rules_" + customerId, 0L, "failed", e.getMessage()); throw e; } finally { redisTemplate.delete(lockKey); } } /** * 批量更新缓存 - 性能优化 */ public void batchUpdateCache(List customerIds) { // 分批处理,避免阻塞 int batchSize = 10; for (int i = 0; i < customerIds.size(); i += batchSize) { List batch = customerIds.subList(i, Math.min(i + batchSize, customerIds.size())); CompletableFuture.runAsync(() -> { batch.parallelStream().forEach(this::updateAlertRulesCache); }); } } private void updateSyncStatus(Long customerId, String cacheKey, Long version, String status, String errorMessage) { TAlertCacheSync syncRecord = TAlertCacheSync.builder() .customerId(customerId) .cacheKey(cacheKey) .version(version) .lastSyncTime(LocalDateTime.now()) .syncStatus(status) .errorMessage(errorMessage) .build(); cacheSyncMapper.insertOrUpdate(syncRecord); } } ``` ### 3. 统一消息发布器 ```java @Service @Slf4j public class UnifiedMessagePublisher { @Autowired private WeChatNotifier weChatNotifier; @Autowired private SmsNotifier smsNotifier; @Autowired private WebSocketNotifier webSocketNotifier; @Autowired private MessageQueueProducer messageProducer; /** * 统一消息发布入口 */ public void publishAlert(AlertMessage alertMessage) { // 1. 消息预处理 UnifiedMessage unifiedMessage = buildUnifiedMessage(alertMessage); // 2. 渠道路由 List channels = routeChannels(alertMessage); // 3. 并行发送 List> futures = channels.stream() .map(channel -> CompletableFuture.supplyAsync(() -> sendToChannel(unifiedMessage, channel))) .collect(Collectors.toList()); // 4. 结果汇总 CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) .thenRun(() -> { List results = futures.stream() .map(CompletableFuture::join) .collect(Collectors.toList()); logResults(alertMessage, results); }); } /** * 构建统一消息模型 */ private UnifiedMessage buildUnifiedMessage(AlertMessage alertMessage) { return UnifiedMessage.builder() .messageId(generateMessageId()) .messageType("alert") .subType(alertMessage.getAlertType()) .title(buildTitle(alertMessage)) .content(buildContent(alertMessage)) .priority(mapPriority(alertMessage.getSeverityLevel())) .urgency(mapUrgency(alertMessage.getSeverityLevel())) .sender(buildSender()) .target(buildTarget(alertMessage)) .delivery(buildDelivery(alertMessage)) .metadata(buildMetadata(alertMessage)) .build(); } /** * 渠道智能路由 */ private List routeChannels(AlertMessage alertMessage) { List channels = new ArrayList<>(); // 基于严重程度决定渠道 String severity = alertMessage.getSeverityLevel(); List enabledChannels = alertMessage.getEnabledChannels(); if (enabledChannels.contains("wechat")) { channels.add(NotificationChannel.WECHAT); } if (enabledChannels.contains("message")) { channels.add(NotificationChannel.INTERNAL_MESSAGE); } // Critical级别强制WebSocket推送 if ("critical".equals(severity)) { channels.add(NotificationChannel.WEBSOCKET); } // 高优先级添加短信通道 if (Arrays.asList("critical", "high").contains(severity) && enabledChannels.contains("sms")) { channels.add(NotificationChannel.SMS); } return channels; } /** * 发送到指定渠道 */ private NotificationResult sendToChannel(UnifiedMessage message, NotificationChannel channel) { try { switch (channel) { case WECHAT: return weChatNotifier.send(message); case SMS: return smsNotifier.send(message); case WEBSOCKET: return webSocketNotifier.send(message); case INTERNAL_MESSAGE: return insertInternalMessage(message); default: return NotificationResult.failed("未知渠道"); } } catch (Exception e) { log.error("发送消息失败: channel={}, messageId={}", channel, message.getMessageId(), e); return NotificationResult.failed(e.getMessage()); } } } ``` ## 🔧 前端实现 (ljwx-bigscreen优化) ### 1. 缓存订阅管理器增强 ```python class AlertRulesCacheSubscriber: """增强版Redis缓存订阅管理器""" def __init__(self): self.redis_bigscreen = RedisHelper() # DB=0 self.redis_boot = redis.Redis(host='127.0.0.1', port=6379, password='123456', db=1) # DB=1 self.local_cache = {} self.cache_stats = { 'hits': 0, 'misses': 0, 'updates': 0, 'errors': 0 } self.running = True def start_subscriber(self): """启动缓存订阅器""" def subscriber_thread(): pubsub = self.redis_bigscreen.pubsub() pubsub.subscribe('alert_rules_channel') logger.info("告警规则缓存订阅器已启动") for message in pubsub.listen(): if not self.running: break if message['type'] == 'message': self.handle_cache_update(message['data']) Thread(target=subscriber_thread, daemon=True).start() def handle_cache_update(self, message): """处理缓存更新消息 - 增强版本""" try: # 解析消息: "update:customer_id:version" parts = message.decode('utf-8').split(':') if len(parts) >= 2 and parts[0] == 'update': customer_id = parts[1] version = int(parts[2]) if len(parts) > 2 else 0 # 检查是否需要更新 if self.should_update_cache(customer_id, version): success = self.refresh_local_cache(customer_id) if success: self.cache_stats['updates'] += 1 logger.info(f"缓存更新成功: customer_id={customer_id}, version={version}") else: self.cache_stats['errors'] += 1 except Exception as e: self.cache_stats['errors'] += 1 logger.error(f"处理缓存更新失败: {e}") def get_alert_rules(self, customer_id): """三层缓存获取告警规则 - 性能优化""" cache_key = f"rules:{customer_id}" # L1: 内存缓存 if cache_key in self.local_cache: cached_data = self.local_cache[cache_key] if time.time() - cached_data['timestamp'] < 300: # 5分钟有效 self.cache_stats['hits'] += 1 return cached_data['rules'] self.cache_stats['misses'] += 1 # L2: ljwx-boot Redis缓存 try: boot_cache_key = f"alert_rules_{customer_id}" cached_data = self.redis_boot.get(boot_cache_key) if cached_data: data = json.loads(cached_data) rules = data.get('rules', []) # 更新L1缓存 self.local_cache[cache_key] = { 'rules': rules, 'timestamp': time.time(), 'version': data.get('version', 0) } return rules except Exception as e: logger.error(f"从ljwx-boot Redis获取规则失败: {e}") # L3: 数据库兜底 try: return self.get_rules_from_database(customer_id) except Exception as e: logger.error(f"数据库兜底查询失败: {e}") return [] def get_cache_stats(self): """获取缓存统计信息""" total_requests = self.cache_stats['hits'] + self.cache_stats['misses'] hit_rate = (self.cache_stats['hits'] / total_requests * 100) if total_requests > 0 else 0 return { 'hit_rate': round(hit_rate, 2), 'total_hits': self.cache_stats['hits'], 'total_misses': self.cache_stats['misses'], 'cache_updates': self.cache_stats['updates'], 'cache_errors': self.cache_stats['errors'], 'local_cache_size': len(self.local_cache) } ``` ### 2. 高性能告警生成器 ```python class HighPerformanceAlertGenerator: """高性能告警生成器 - 异步队列处理""" def __init__(self): self.alert_queue = asyncio.Queue(maxsize=10000) self.batch_size = 100 self.max_wait_time = 2.0 self.workers = [] self.rule_engine = AlertRuleEngine() self.cache_subscriber = AlertRulesCacheSubscriber() # 性能统计 self.performance_stats = { 'total_processed': 0, 'total_generated': 0, 'avg_processing_time': 0.0, 'queue_size': 0, 'cache_hit_rate': 0.0 } async def start_workers(self, worker_count=4): """启动异步工作者""" for i in range(worker_count): worker = asyncio.create_task(self._worker_loop(f"worker-{i}")) self.workers.append(worker) # 启动缓存订阅器 self.cache_subscriber.start_subscriber() logger.info(f"告警生成器已启动 {worker_count} 个工作者") async def submit_health_data(self, health_data, health_data_id=None): """提交健康数据到处理队列""" try: item = { 'health_data': health_data, 'health_data_id': health_data_id, 'timestamp': time.time(), 'device_sn': health_data.get('deviceSn', '') } await self.alert_queue.put(item) return True except asyncio.QueueFull: logger.warning("告警处理队列已满,丢弃请求") return False async def _worker_loop(self, worker_name): """工作者主循环""" batch = [] last_process_time = time.time() while True: try: # 收集批次 while len(batch) < self.batch_size and (time.time() - last_process_time) < self.max_wait_time: try: item = await asyncio.wait_for(self.alert_queue.get(), timeout=0.5) batch.append(item) except asyncio.TimeoutError: break # 处理批次 if batch: await self._process_batch(batch, worker_name) batch.clear() last_process_time = time.time() except Exception as e: logger.error(f"{worker_name} 异常: {e}") batch.clear() async def _process_batch(self, health_data_batch, worker_name): """批量处理健康数据""" start_time = time.time() processed_count = 0 generated_alerts = 0 try: # 按customer_id分组批次 customer_batches = defaultdict(list) for item in health_data_batch: customer_id = item['health_data'].get('customer_id') or item['health_data'].get('customerId') customer_batches[customer_id].append(item) # 并行处理每个客户的数据 tasks = [] for customer_id, customer_data in customer_batches.items(): task = self._process_customer_batch(customer_id, customer_data) tasks.append(task) results = await asyncio.gather(*tasks, return_exceptions=True) # 统计结果 for result in results: if isinstance(result, dict): processed_count += result.get('processed', 0) generated_alerts += result.get('generated', 0) except Exception as e: logger.error(f"{worker_name} 批量处理异常: {e}") # 更新性能统计 processing_time = time.time() - start_time self.performance_stats['total_processed'] += processed_count self.performance_stats['total_generated'] += generated_alerts self.performance_stats['avg_processing_time'] = ( self.performance_stats['avg_processing_time'] * 0.9 + processing_time * 0.1 ) self.performance_stats['queue_size'] = self.alert_queue.qsize() logger.info(f"{worker_name} 批量处理完成: 处理{processed_count}条, 生成告警{generated_alerts}条, 耗时{processing_time:.3f}s") async def _process_customer_batch(self, customer_id, health_data_list): """处理单个客户的健康数据批次""" try: # 1. 批量获取规则(一次查询) rules = self.cache_subscriber.get_alert_rules(customer_id) if not rules: return {'processed': len(health_data_list), 'generated': 0} # 2. 编译规则(一次编译) compiled_rules = self.rule_engine.compile_rules(rules) # 3. 批量评估 generated_alerts = 0 for item in health_data_list: alerts = await self.rule_engine.evaluate_rules_async( item['health_data'], item['health_data_id'], compiled_rules ) generated_alerts += len(alerts) return {'processed': len(health_data_list), 'generated': generated_alerts} except Exception as e: logger.error(f"处理客户批次失败: customer_id={customer_id}, error={e}") return {'processed': 0, 'generated': 0} def get_performance_stats(self): """获取性能统计""" cache_stats = self.cache_subscriber.get_cache_stats() self.performance_stats['cache_hit_rate'] = cache_stats['hit_rate'] return { **self.performance_stats, 'cache_stats': cache_stats } ``` ### 3. 复合规则引擎 ```python class AlertRuleEngine: """告警规则引擎 - 支持复合条件""" def __init__(self): self.condition_cache = {} self.evaluation_history = defaultdict(list) def compile_rules(self, rules): """规则预编译""" compiled_rules = { 'single_rules': defaultdict(list), 'composite_rules': [], 'complex_rules': [], 'priority_index': defaultdict(list) } for rule in rules: if not rule.get('is_active', True): continue rule_category = rule.get('rule_category', 'SINGLE') priority = rule.get('priority_level', 5) if rule_category == 'SINGLE': physical_sign = rule.get('physical_sign') if physical_sign: compiled_rule = self._compile_single_rule(rule) compiled_rules['single_rules'][physical_sign].append(compiled_rule) compiled_rules['priority_index'][priority].append(compiled_rule) elif rule_category == 'COMPOSITE': compiled_rule = self._compile_composite_rule(rule) if compiled_rule: compiled_rules['composite_rules'].append(compiled_rule) compiled_rules['priority_index'][priority].append(compiled_rule) elif rule_category == 'COMPLEX': compiled_rule = self._compile_complex_rule(rule) if compiled_rule: compiled_rules['complex_rules'].append(compiled_rule) compiled_rules['priority_index'][priority].append(compiled_rule) return compiled_rules async def evaluate_rules_async(self, health_data, health_data_id, compiled_rules): """异步规则评估""" triggered_alerts = [] device_sn = health_data.get('deviceSn', '') try: # 1. 按优先级评估 for priority in sorted(compiled_rules['priority_index'].keys()): priority_rules = compiled_rules['priority_index'][priority] for rule in priority_rules: # 检查生效时间 if not self._is_rule_effective(rule): continue # 根据规则类型评估 alert = None if rule['type'] == 'single': alert = await self._evaluate_single_rule_async(rule, health_data, health_data_id) elif rule['type'] == 'composite': alert = await self._evaluate_composite_rule_async(rule, health_data, health_data_id) elif rule['type'] == 'complex': alert = await self._evaluate_complex_rule_async(rule, health_data, health_data_id) if alert: # 检查告警抑制 if not self._is_suppressed(alert, rule): triggered_alerts.append(alert) # 设置冷却期 self._set_cooldown(alert, rule) # 2. 批量保存告警 if triggered_alerts: await self._save_alerts_batch(triggered_alerts) except Exception as e: logger.error(f"规则评估异常: device_sn={device_sn}, error={e}") return triggered_alerts async def _evaluate_composite_rule_async(self, rule, health_data, health_data_id): """复合规则异步评估""" try: condition_expr = rule.get('condition_expression', {}) conditions = condition_expr.get('conditions', []) logical_op = condition_expr.get('logical_operator', 'AND') if not conditions: return None # 并行评估所有条件 condition_tasks = [] for condition in conditions: task = self._evaluate_condition_async(condition, health_data) condition_tasks.append(task) condition_results = await asyncio.gather(*condition_tasks) # 逻辑组合 if logical_op == 'AND': final_result = all(condition_results) elif logical_op == 'OR': final_result = any(condition_results) else: final_result = False if final_result: return await self._create_alert_async(rule, health_data, health_data_id, { 'condition_results': condition_results, 'trigger_type': 'composite' }) except Exception as e: logger.error(f"复合规则评估失败: rule_id={rule.get('id')}, error={e}") return None async def _evaluate_condition_async(self, condition, health_data): """异步条件评估""" try: physical_sign = condition['physical_sign'] operator = condition['operator'] threshold = condition['threshold'] duration = condition.get('duration_seconds', 0) value = health_data.get(physical_sign) if value is None: return False # 基础条件检查 condition_met = self._check_condition(float(value), operator, threshold) # 持续时间检查 if condition_met and duration > 0: condition_met = await self._check_duration_async( health_data, physical_sign, operator, threshold, duration ) return condition_met except Exception as e: logger.error(f"条件评估失败: condition={condition}, error={e}") return False def _check_condition(self, value, operator, threshold): """检查单个条件""" if operator == '>': return value > threshold elif operator == '<': return value < threshold elif operator == '>=': return value >= threshold elif operator == '<=': return value <= threshold elif operator == '==': return value == threshold else: return False async def _check_duration_async(self, health_data, physical_sign, operator, threshold, duration): """异步检查持续时间条件""" device_sn = health_data.get('deviceSn', '') condition_key = f"{device_sn}:{physical_sign}:{operator}:{threshold}" # 获取历史评估记录 history = self.evaluation_history[condition_key] current_time = time.time() # 清理过期记录 history[:] = [t for t in history if current_time - t < duration] # 添加当前时间 history.append(current_time) # 检查是否满足持续时间要求 return len(history) >= 3 # 至少3次连续满足条件 async def _save_alerts_batch(self, alerts): """批量保存告警""" try: for alert in alerts: alert_info = AlertInfo( rule_id=alert['rule_id'], alert_type=alert['alert_type'], device_sn=alert['device_sn'], alert_desc=alert['alert_desc'], severity_level=alert['severity_level'], alert_status='pending', alert_timestamp=get_now(), health_id=alert.get('health_data_id'), user_id=alert.get('user_id'), org_id=alert.get('org_id'), latitude=alert.get('latitude'), longitude=alert.get('longitude'), trigger_conditions=json.dumps(alert.get('trigger_conditions', {})), evaluation_context=json.dumps(alert.get('evaluation_context', {})) ) db.session.add(alert_info) db.session.commit() logger.info(f"批量保存告警成功: {len(alerts)}条") except Exception as e: db.session.rollback() logger.error(f"批量保存告警失败: {e}") ``` ## 🎨 前端管理界面 (ljwx-admin) ### 1. 规则配置向导组件 ```vue ``` ### 2. 规则列表管理页面 ```vue ``` ## 📊 性能监控与统计 ### 1. 性能监控接口 ```python @app.route('/api/alert_rules/performance_stats', methods=['GET']) def get_alert_rules_performance_stats(): """获取告警规则系统性能统计""" try: # 获取高性能生成器统计 generator_stats = high_performance_generator.get_performance_stats() # 获取缓存统计 cache_subscriber = get_alert_rules_cache_subscriber() cache_stats = cache_subscriber.get_cache_stats() # 获取数据库统计 db_stats = get_database_performance_stats() # 获取告警统计 alert_stats = get_alert_generation_stats() return jsonify({ 'success': True, 'data': { 'performance': { 'generator': generator_stats, 'cache': cache_stats, 'database': db_stats, 'alerts': alert_stats }, 'timestamp': time.time() } }) except Exception as e: logger.error(f"获取性能统计失败: {e}") return jsonify({ 'success': False, 'error': str(e) }), 500 def get_database_performance_stats(): """获取数据库性能统计""" return { 'connection_pool_size': db.engine.pool.size(), 'connection_pool_checked_out': db.engine.pool.checkedout(), 'query_count': getattr(db.engine, '_query_count', 0), 'avg_query_time': getattr(db.engine, '_avg_query_time', 0) } def get_alert_generation_stats(): """获取告警生成统计""" today = datetime.now().date() # 今日告警统计 today_alerts = db.session.query(AlertInfo).filter( func.date(AlertInfo.alert_timestamp) == today ).count() # 按严重程度统计 severity_stats = db.session.query( AlertInfo.severity_level, func.count(AlertInfo.id) ).filter( func.date(AlertInfo.alert_timestamp) == today ).group_by(AlertInfo.severity_level).all() # 按规则类型统计 rule_type_stats = db.session.query( AlertRules.rule_type, func.count(AlertInfo.id) ).join( AlertInfo, AlertRules.id == AlertInfo.rule_id ).filter( func.date(AlertInfo.alert_timestamp) == today ).group_by(AlertRules.rule_type).all() return { 'today_total': today_alerts, 'severity_distribution': dict(severity_stats), 'rule_type_distribution': dict(rule_type_stats) } ``` ### 2. 监控仪表板页面 ```vue ``` ## 📋 实施计划与部署 ### 阶段一:基础设施准备 (1周) 1. **数据库表结构升级** - 执行表结构变更SQL - 数据迁移和验证 - 索引优化 2. **Redis配置优化** - TTL调整为24小时 - 发布订阅通道配置 - 连接池优化 3. **基础设施监控** - 性能基线建立 - 监控指标配置 ### 阶段二:后端核心实现 (2周) 1. **规则引擎开发** - 单体征规则兼容 - 复合规则引擎 - 规则预编译优化 2. **缓存同步优化** - 三层缓存架构 - 跨DB订阅机制 - 容错和恢复 3. **消息发布统一** - 统一消息模型 - 多渠道路由 - 异步处理队列 ### 阶段三:前端界面开发 (2周) 1. **规则配置向导** - 步骤式配置界面 - 实时预览功能 - 条件可视化编辑 2. **规则管理页面** - 列表展示和筛选 - 批量操作功能 - 性能监控面板 3. **性能监控仪表板** - 实时性能图表 - 告警统计分析 - 系统健康状态 ### 阶段四:性能优化和测试 (1周) 1. **性能压力测试** - 1000并发处理验证 - 响应时间优化 - 内存使用优化 2. **功能集成测试** - 端到端流程测试 - 异常场景验证 - 兼容性测试 ### 阶段五:生产部署 (1周) 1. **灰度发布** - 小流量验证 - 性能监控 - 问题快速响应 2. **全量发布** - 配置迁移 - 数据同步 - 性能调优 ## 🎯 预期效果 ### 性能提升指标 - **规则评估速度**: 提升80%以上 - **并发处理能力**: 支持1000+并发 - **内存使用**: 减少40% - **响应时间**: 平均50ms以下 ### 功能增强效果 - **规则表达能力**: 支持复杂的多体征关联 - **管理效率**: 可视化配置,降低80%配置时间 - **系统稳定性**: 告警抑制,减少90%重复告警 - **运维便利性**: 完整监控体系,问题快速定位 ### 业务价值 - **告警准确性**: 减少误报85%以上 - **响应速度**: 告警延迟降至秒级 - **运维成本**: 减少人工干预60% - **用户体验**: 更精准的健康监护服务 这个完整的实施方案整合了所有优化策略,提供了从数据库设计、后端实现、前端界面到部署监控的全流程解决方案,可以直接按照计划逐步实施落地。