zoukankan      html  css  js  c++  java
  • 熔断器原理

    一般在微服架构中,有一个组件角色叫熔断器。顾名思义,熔断器起的作用就是在特定的场景下关掉当前的通路,从而起到保护整个系统的效果。

    在微服务架构中,一般我们的独立服务是比较多的,每个独立服务之间划分责任边界,并通过约定协议接口来进行通信。当我们的调用链路复杂依赖多时,很可能会发生雪崩效应。

    假设有这么一个场景,有A, B, C, D四个独立服务,A会依赖B,C,D;当D发生负载过高或网络异常等导致响应过慢或超时时,很可能A会因此堆积过多的等待链接,从而导致A的状态也转为异常,后面依赖到A的其他服务跟着发生链式反应,这将会导致大面积的服务不可用,即使本来是一些没有依赖到B,C,D的服务。如下图所示: 
    这里写图片描述

    这不是我们希望看到的结果,所以这个时候熔断器可以派上用场。最简单的做法,我们为每个依赖服务配置一个熔断器开关,正常情况下是关闭的,也就是可以正常发起请求;当请求失败(超时或者其他异常)次数超过预设值时,熔断器自动打开,这时所有经过这个熔断器的请求都会直接返回失败,并没有真正到达所依赖的服务上。这时服务A本身仍然是能正常服务的, 如下图所示: 
    这里写图片描述

    那么熔断器具体又是怎么工作的呢?来看下,一个拥有基本功能的熔断器的状态机大体是这样子的: 
    这里写图片描述

    主要在三种状态中转换:

    • 关闭状态 
      当熔断器处于关闭状态时,请求是可以被放行的; 
      当熔断器统计的失败次数触发开关时,转为打开状态。
    • 打开状态 
      当熔断器处于打开状态时,所有请求都是不被放行的,直接返回失败; 
      只有在经过一个设定的时间窗口周期后,熔断器才会转换到半开状态
    • 半开状态 
      当熔断器处于半开状态时,当前只能有一个请求被放行; 
      这个被放行的请求获得远端服务的响应后,假如是成功的,熔断器转换为关闭状态,否则转换到打开状态。

    最后,基于这个状态机,我用Golang实现了一个只包含最基本功能的熔断器:github.com/moxiaomomo/circuitbreaker, 有兴趣可以参考一下,也欢迎指正。

    主要用法如下:

    // 创建一个熔断器实例,指定熔断时间窗口和失败触发开关阈值等
    cbs := NewCirucuitBreaker(time.Second, 150, 20)
    // 向熔断器注册command(可以理解为对应的服务请求id)
    testcmd := "call_serviceB"
    suc := cbs.RegisterCommandAsDefault(testcmd)
    
    // 向熔断器报告当前command的执行结果(成功或失败)
    cbs.Report(testcmd, false)
    cbs.Report(testcmd, true)
    // ...
    
    // 向熔断器询问当前该command是否能被执行
    execAllow := cbs.AllowExec(testcmd)
  • 相关阅读:
    《疯狂Java讲义》(二十) ---- 系统相关类
    《疯狂Java讲义》(十九)---- 与用户交互
    《疯狂Java讲义》(十八)---- JAR文件
    《疯狂Java讲义》(十七)---- 对象与垃圾回收
    《疯狂Java讲义》(十六)---- 枚举类
    《疯狂Java讲义》(十五)---- 内部类
    疯狂Java讲义(十四)---- 抽象类和接口
    疯狂Java讲义(十三)---- 类成员
    疯狂Java讲义(十二)---- equals
    Algorithm: Euclid's algorithm of finding GCD
  • 原文地址:https://www.cnblogs.com/yy1234/p/9522541.html
Copyright © 2011-2022 走看看