当前位置: 首页 > article >正文

[java] 简单的熔断器scala语言案例

failureRateInterval时间内如果addEx(错误)达到 maxFailuresPerInterval 次数,则fused方法返回true,表示触发熔断,进入冷却期coolingInterval,冷却期内fused方法返回true,冷却期过后进入下一个错误统计周期。

scala语言完成

import scala.collection.mutable
case class Excp(ts: Long, throwable: Throwable)

trait ExceptionStrategy {
}

case class FailureRateExit(maxFailuresPerInterval: Int, failureRateInterval: Int, coolingInterval: Int) extends ExceptionStrategy {
  val LOG: Logger = org.slf4j.LoggerFactory.getLogger(this.getClass)


  private val exceptionQueue: mutable.Queue[Excp] = mutable.Queue.empty
  // exceptionQueue += Excp(0L, new RuntimeException())
  private var lastFuseTs: Long = 0L

  def fused(): Boolean = {
    val curr = System.currentTimeMillis()
    if ((curr - lastFuseTs) / 1000 <= coolingInterval) {
      LOG.info(s"fusing cooling, fist error ts:${exceptionQueue.head.ts}, last error ts:${exceptionQueue.last.ts}")
      exceptionQueue.clear()
      return true
    }
    cleanup(curr)
    val trigger = exceptionQueue.size >= maxFailuresPerInterval && exceptionQueue.head.ts - exceptionQueue.last.ts <= failureRateInterval
    if (trigger) {
      lastFuseTs = curr
      LOG.info(s"fusing triggered, fist error ts:${exceptionQueue.head.ts}, last error ts:${exceptionQueue.last.ts}, total errors:${exceptionQueue.size}")
    }
    trigger
  }

  def addEx(ex: Exception): Unit = {
    val curr = System.currentTimeMillis()
    exceptionQueue += Excp(curr, ex)
    cleanup(curr)
  }

  private def cleanup(curr: Long = System.currentTimeMillis()): Unit = {
    exceptionQueue.dequeueAll(e => (curr - e.ts) / 1000 >= failureRateInterval)
    exceptionQueue.dequeueAll(e => exceptionQueue.size > maxFailuresPerInterval * 2 && e != exceptionQueue.last && e != exceptionQueue.head)
  }
}

测试代码:

import org.scalatest.funsuite.AnyFunSuite
import scala.util.Random

class StrategyTest extends AnyFunSuite {

  test("fail-rate") {
    val f = FailureRateExit(3, 10, 15)
    while (true) {
      f.addEx(new RuntimeException())
      println(f.fused())
      Thread.sleep(Random.nextInt(8 * 1000))
    }
  }
}

测试结果:

false
false
false
false
13:52:03.519 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:30 --- fusing triggered, fist error ts:1734414718275, last error ts:1734414723512, total errors:3
true
13:52:10.202 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:22 --- fusing cooling, fist error ts:1734414722743, last error ts:1734414730202
true
13:52:18.120 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:22 --- fusing cooling, fist error ts:1734414738120, last error ts:1734414738120
true
false
false
false
false
false
false
13:52:55.780 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:30 --- fusing triggered, fist error ts:1734414768116, last error ts:1734414775780, total errors:3
true
13:53:00.976 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:22 --- fusing cooling, fist error ts:1734414775249, last error ts:1734414780976
true
13:53:03.931 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:22 --- fusing cooling, fist error ts:1734414783931, last error ts:1734414783931
true
13:53:07.628 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:22 --- fusing cooling, fist error ts:1734414787628, last error ts:1734414787628
true
false
false
false
13:53:28.360 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:30 --- fusing triggered, fist error ts:1734414800129, last error ts:1734414808359, total errors:3
true
13:53:35.734 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:22 --- fusing cooling, fist error ts:1734414808359, last error ts:1734414815734
true
13:53:42.517 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:22 --- fusing cooling, fist error ts:1734414822514, last error ts:1734414822514
true
false
false
13:53:49.223 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:30 --- fusing triggered, fist error ts:1734414824804, last error ts:1734414829223, total errors:3
true
13:53:50.351 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:22 --- fusing cooling, fist error ts:1734414824804, last error ts:1734414830351
true
13:53:57.470 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:22 --- fusing cooling, fist error ts:1734414837470, last error ts:1734414837470
true
13:54:04.618 [ScalaTest-run-running-StrategyTest] [INFO ] FailureRateExit:22 --- fusing cooling, fist error ts:1734414844618, last error ts:1734414844618
true
false
false

使用方式伪代码:

  private val strategy: FailureRateExit = FailureRateExit(failureRateInterval, maxFailuresPerInterval, failCoolingInterval)
       
	   try {
          if(!strategy.fused){
		  // 执行正常逻辑
		  }else{
		  // 忽略
		  }
        } catch {
          case ex: Exception =>
		    // 添加异常到熔断器
            strategy.addEx(ex)
        }

http://www.kler.cn/a/444890.html

相关文章:

  • 【Flutter_Web】Flutter编译Web第二篇(webview篇):flutter_inappwebview如何改造方法,变成web之后数据如何交互
  • 【笔记】深度学习模型评估指标
  • springboot中Controller内文件上传到本地以及阿里云
  • ABAP SQL 取日期+时间最新的一条数据
  • pip离线安装一个github仓库
  • docker(wsl)命令 帮助文档
  • linux网络套接字 | 深度解析守护进程 | 实现tcp服务守护进程化
  • 联合目标检测与图像分类提升数据不平衡场景下的准确率
  • Linux创建普通用户和修改主机名
  • python tif处理 GDAL安装方法
  • Harmonyos多线程之Worker基本使用
  • 前端跨越方式有哪些
  • Jenkins 中 写 shell 命令执行失败,检测失败问题
  • Linux常用命令【真·常用】
  • DGCN论文解读
  • Python读取Excel批量写入到PPT生成词卡
  • 配置免密登陆服务器
  • python快速接入阿里云百炼大模型
  • 【数据分析】数据分析流程优化:从数据采集到可视化的全面指南
  • 一篇文章理解前端的请求头和响应头含义
  • 打 印 菱 形
  • Gartner发布2025年网络安全主要趋势:实现转型和嵌入弹性两大主题下的9个趋势
  • Linux性能监控命令_nmon 安装与使用以及生成分析Excel图表
  • 基于注意力机制的ResNet优化算法(三种注意力机制+源码+pytorch)
  • 4、交换机IP接口功能
  • git 删除鉴权缓存及账号信息