RuleCheckService.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. namespace app\common\service;
  3. use think\Db;
  4. use think\Cache;
  5. class RuleCheckService
  6. {
  7. // 缓存前缀
  8. const CACHE_PREFIX = 'risk_control:rule:';
  9. // 缓存时间(秒)
  10. const CACHE_TIME = 3600;
  11. /**
  12. * 检查频率规则
  13. * @param array $detail 规则详情
  14. * @param array $eventData 事件数据
  15. * @return bool
  16. */
  17. public function checkFrequencyRule(array $detail, array $eventData)
  18. {
  19. $cacheKey = self::CACHE_PREFIX . 'frequency:' . $detail['rule_id'] . ':' . $eventData[$detail['object_type']];
  20. // 获取时间窗口内的记录数
  21. $count = $this->getFrequencyCount($detail, $eventData, $cacheKey);
  22. // 根据逻辑类型判断
  23. switch ($detail['logic_type']) {
  24. case 'gt': // 大于
  25. return $count > $detail['logic_value'];
  26. case 'gte': // 大于等于
  27. return $count >= $detail['logic_value'];
  28. case 'lt': // 小于
  29. return $count < $detail['logic_value'];
  30. case 'lte': // 小于等于
  31. return $count <= $detail['logic_value'];
  32. case 'eq': // 等于
  33. return $count == $detail['logic_value'];
  34. default:
  35. return false;
  36. }
  37. }
  38. /**
  39. * 获取频率计数
  40. * @param array $detail
  41. * @param array $eventData
  42. * @param string $cacheKey
  43. * @return int
  44. */
  45. private function getFrequencyCount(array $detail, array $eventData, string $cacheKey)
  46. {
  47. // 先查缓存
  48. $count = Cache::get($cacheKey);
  49. if ($count !== false) {
  50. return $count;
  51. }
  52. // 计算时间窗口
  53. $endTime = $eventData['timestamp'];
  54. $startTime = $endTime - $detail['time_window'];
  55. // 查询数据库
  56. $count = Db::name('fk_exception_records')
  57. ->where([
  58. 'rule_id' => $detail['rule_id'],
  59. 'object_type' => $detail['object_type'],
  60. 'object_value' => $eventData[$detail['object_type']]
  61. ])
  62. ->where('create_time', 'between', [$startTime, $endTime])
  63. ->count();
  64. // 设置缓存
  65. Cache::set($cacheKey, $count, min($detail['time_window'], self::CACHE_TIME));
  66. return $count;
  67. }
  68. /**
  69. * 检查统计规则
  70. * @param array $detail
  71. * @param array $eventData
  72. * @return bool
  73. */
  74. public function checkStatisticsRule(array $detail, array $eventData)
  75. {
  76. $cacheKey = self::CACHE_PREFIX . 'statistics:' . $detail['rule_id'] . ':' . $eventData[$detail['object_type']];
  77. // 获取统计数据
  78. $statistics = $this->getStatisticsData($detail, $eventData, $cacheKey);
  79. // 根据逻辑类型判断
  80. switch ($detail['logic_type']) {
  81. case 'gt': // 大于
  82. return $statistics > $detail['logic_value'];
  83. case 'gte': // 大于等于
  84. return $statistics >= $detail['logic_value'];
  85. case 'lt': // 小于
  86. return $statistics < $detail['logic_value'];
  87. case 'lte': // 小于等于
  88. return $statistics <= $detail['logic_value'];
  89. case 'eq': // 等于
  90. return $statistics == $detail['logic_value'];
  91. default:
  92. return false;
  93. }
  94. }
  95. /**
  96. * 获取统计数据
  97. * @param array $detail
  98. * @param array $eventData
  99. * @param string $cacheKey
  100. * @return float
  101. */
  102. private function getStatisticsData(array $detail, array $eventData, string $cacheKey)
  103. {
  104. // 先查缓存
  105. $data = Cache::get($cacheKey);
  106. if ($data !== false) {
  107. return $data;
  108. }
  109. // 计算时间窗口
  110. $endTime = $eventData['timestamp'];
  111. $startTime = $endTime - $detail['time_window'];
  112. // 查询数据库
  113. $query = Db::name('fk_exception_records')
  114. ->where([
  115. 'rule_id' => $detail['rule_id'],
  116. 'object_type' => $detail['object_type'],
  117. 'object_value' => $eventData[$detail['object_type']]
  118. ])
  119. ->where('create_time', 'between', [$startTime, $endTime]);
  120. // 根据统计类型计算
  121. switch ($detail['statistics_type']) {
  122. case 'avg': // 平均值
  123. $data = $query->avg('exception_level');
  124. break;
  125. case 'sum': // 总和
  126. $data = $query->sum('exception_level');
  127. break;
  128. case 'max': // 最大值
  129. $data = $query->max('exception_level');
  130. break;
  131. case 'min': // 最小值
  132. $data = $query->min('exception_level');
  133. break;
  134. default:
  135. $data = 0;
  136. }
  137. // 设置缓存
  138. Cache::set($cacheKey, $data, min($detail['time_window'], self::CACHE_TIME));
  139. return $data;
  140. }
  141. }