circuit

在Hystrix调用服务时,难免会遇到异常,如对方服务不可用,在这种情况下如果仍然不停地调用就是不必要的,在Hystrix中可以配置使用circuit,当达到一定程度错误,就会自动调用fallback方法而不是用run方法。

配置

在Command的构造函数的CommandPropertiesDefaults中可以配置以下的参数

    circuitBreakerRequestVolumeThreshold; // 在时间窗口(默认10s)中需要达到的访问数量	默认20
circuitBreakerSleepWindowInMilliseconds; // 触发circuit后重试的间隔 默认5s
circuitBreakerEnabled; // 是否启用circuit 默认启用
circuitBreakerErrorThresholdPercentage; // 在时间窗口中触发circuit的错误访问百分比 默认50%

从配置可以粗略看出,circuit就是在一个时间窗口内,当访问达到一定数量且错误率达到一定阈值就直接调用fallback,过一定时间之后会尝试,如果成功就重新开始时间窗口,如果失败继续调用fallback,如此往复。

实现

Hystrix的默认circuit实现是HystrixCircuitBreakerImpl

//这个是主要的逻辑,用于判断是否进行circuit,返回false则直接调用fallback,返回true则调用run
@Override
public boolean allowRequest() {
//判断是否强制开启circuit,使用circuitBreakerForceOpen配置
if (properties.circuitBreakerForceOpen().get()) {
// properties have asked us to force the circuit open so we will allow NO requests
return false;
}
//判断是否强制关闭circuit,使用circuitBreakerForceClosed配置
if (properties.circuitBreakerForceClosed().get()) {
// we still want to allow isOpen() to perform it's calculations so we simulate normal behavior
isOpen();
// properties have asked us to ignore errors so we will ignore the results of isOpen and just allow all traffic through
return true;
}
//调用isOpen和allowSingleTest,前者是控制流量和错误率,后者是使用
return !isOpen() || allowSingleTest();
}
//判断是否触发circuit
@Override
public boolean isOpen() {
if (circuitOpen.get()) {
// if we're open we immediately return true and don't bother attempting to 'close' ourself as that is left to allowSingleTest and a subsequent successful test to close
return true;
}
//healthCounts是一个记录请求详细信息的subject,底层是注册在Rxjava上的
// we're closed, so let's see if errors have made us so we should trip the circuit open
HealthCounts health = metrics.getHealthCounts(); //校验是否到达对应的流量
// check if we are past the statisticalWindowVolumeThreshold
if (health.getTotalRequests() < properties.circuitBreakerRequestVolumeThreshold().get()) {
// we are not past the minimum volume threshold for the statisticalWindow so we'll return false immediately and not calculate anything
return false;
}
//校验是否到达对应的错误率
if (health.getErrorPercentage() < properties.circuitBreakerErrorThresholdPercentage().get()) {
return false;
} else {
//开启circuit,使用CAS来处理多线程的征用
// our failure rate is too high, trip the circuit
if (circuitOpen.compareAndSet(false, true)) {
// if the previousValue was false then we want to set the currentTime
circuitOpenedOrLastTestedTime.set(System.currentTimeMillis());
return true;
} else {
// How could previousValue be true? If another thread was going through this code at the same time a race-condition could have
// caused another thread to set it to true already even though we were in the process of doing the same
// In this case, we know the circuit is open, so let the other thread set the currentTime and report back that the circuit is open
return true;
}
}
} //当开启circuit在一段时间后需要重试,allowRequest中使用||短路符号来触发时间校验
public boolean allowSingleTest() {
//获得上次成功运行或测试时间
long timeCircuitOpenedOrWasLastTested = circuitOpenedOrLastTestedTime.get();
// 1) if the circuit is open
// 2) and it's been longer than 'sleepWindow' since we opened the circuit
//如果circuit开启并时间间隔大于响应的时间则进行测试,为了避免多线程的问题,这里也使用CAS进行比较时间
if (circuitOpen.get() && System.currentTimeMillis() > timeCircuitOpenedOrWasLastTested + properties.circuitBreakerSleepWindowInMilliseconds().get()) {
// We push the 'circuitOpenedTime' ahead by 'sleepWindow' since we have allowed one request to try.
// If it succeeds the circuit will be closed, otherwise another singleTest will be allowed at the end of the 'sleepWindow'.
if (circuitOpenedOrLastTestedTime.compareAndSet(timeCircuitOpenedOrWasLastTested, System.currentTimeMillis())) {
// if this returns true that means we set the time so we'll return true to allow the singleTest
// if it returned false it means another thread raced us and allowed the singleTest before we did
return true;
}
}
return false;
}

总结

Hystrix的circuit可以减少发生错误时的无用调用,其中最关键的是其中的HealthCounts用来记录错误率和流量,同时这个记录不是实时的是有一定的时间间隔的,这个是使用RxJava来实现的,后续会就Rxjava进行研究。

Hystrix框架4--circuit的更多相关文章

  1. Hystrix框架1--入门

    介绍 在开发应用中或多或少会依赖各种外界的服务,利用各个服务来完成自己的业务需求,现在流行的微服务架构更是离不开各个服务之间的调用,这就导致整体应用的可用性依赖于各个依赖服务的可用性. 比如一个依赖3 ...

  2. Hystrix框架5--请求缓存和collapser

    简介 在Hystrix中有个Request的概念,有一些操作需要在request中进行 缓存 在Hystrix调用服务时,如果只是查询接口,可以使用缓存进行优化,从而跳过真实访问请求. 应用 需要启用 ...

  3. Hystrix框架3--线程池

    线程池 在Hystrix中Command默认是运行在一个单独的线程池中的,线程池的名称是根据设定的ThreadPoolKey定义的,如果没有设置那么会使用CommandGroupKey作为线程池. 这 ...

  4. Hystrix框架2--超时

    timeout 在调用第三方服务时有些情况需要对服务响应时间进行把控,当超时的情况下进行fallback的处理 下面来看下超时的案例 public class CommandTimeout exten ...

  5. Hystrix 框架

    雪崩效应的产生原因:当一个服务突然受到高并发的请求,tomcat服务器承受不了的情况下会产生服务堆积,可能导致其他的服务也不可用. 服务保护:当服务产生堆积的时候,对服务实现保护功能. 服务隔离:每个 ...

  6. 微服务(二)hystrix

    特性 1.延迟和失败容忍 防止级联错误,错误回退,优雅降级.快速失败和恢复 线程和信号量隔离 2.实时监控和配置更改 3.并发 并行执行,请求缓存,自动批处理失败请求 总运行流程 当你发出请求后,hy ...

  7. 微服务—熔断器Hystrix

    前言在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元应用间通过服务注册与发现的方式互相依赖. 由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服 ...

  8. 基于hystrix的线程池隔离

    hystrix进行资源隔离,其实是提供了一个抽象,叫做command,就是说,你如果要把对某一个依赖服务的所有调用请求,全部隔离在同一份资源池内 对这个依赖服务的所有调用请求,全部走这个资源池内的资源 ...

  9. 使用Hystrix提高系统可用性

    今天稍微复杂点的互联网应用,服务端基本都是分布式的,大量的服务支撑起整个系统,服务之间也难免有大量的依赖关系,依赖都是通过网络连接起来. (图片来源:https://github.com/Netfli ...

随机推荐

  1. Swift -字符串

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #4dbf56 } p.p2 { margin: 0.0px 0. ...

  2. DataFrame格式化

    1.如果是格式化成Json的話直接 val rdd = df.toJSON.rdd 2.如果要指定格式需要自定义函数如下: //格式化具体字段条目 def formatItem(p:(StructFi ...

  3. SSH框架整合(XML)

    Struts2+Spring+Hibernate导包 Struts2导入jar包 struts2/apps/struts2-blank.war/WEB-INF/lib/*.jar 导入与spring整 ...

  4. python 爬虫(三)

    爬遍整个域名    六度空间理论:任何两个陌生人之间所间隔的人不会超过六个,也就是说最多通过五个人你可以认识任何一个陌生人.通过维基百科我们能够通过连接从一个人连接到任何一个他想连接到的人. 1. 获 ...

  5. KickStart 无人值守安装系统

    一.简介 1.1 什么是PXE PXE(Pre-boot Execution Environment,预启动执行环境)是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支持 ...

  6. ASP.NET - 回滚事务

    SqlConnection con =new SqlConnection(ConnectionDb.conStr);//获取数据库连接 con.Open();//打开连接 SqlTransaction ...

  7. 【SRM】649 t2

    题意 一个数列\(A\),数的范围均在\([0, 2^N-1]\)内,求一个\(B\),使得新生成的数列\(C\)中逆序对最多(\(C_i = A_i xor B\)),输出最多的逆序对.(\(|A| ...

  8. 用ShareSDK 进行第三方分享

    1.首先要先注册自己的appkey在shareSDK官网里面 2.下载shareSDK 文档,可以根据需要下载自己需要的 如图 3.将下载好的shareSDK 解压后加入工程里面 4.添加依赖库 // ...

  9. Poco::JSON::Array 中object 设置preserveInsertionOrder 时,stringify出错-->深入解析

    在使用poco version 1.6.0时 Poco::JSON::Array 在object  设置preserveInsertionOrder =true 时 调用 array.stringif ...

  10. 在线Spirte图定位工具,自动生成CSS

    发现一个在线雪碧图中的图片地位的工具,并且能够自动生成css.spritecow 废话不多说,有图有真相: