spring boot 2 集成 resilience4j

resilience4j 是一款 java 平台轻量级容错库,支持熔断、限流、重试等功能。由于Netflix Hystrix 闭源,我们急需一款功能强大的容错工具库,来保护我们的环境。resilience4j 提供了spring boot 的starter,所以集成resilience4j很简单,但是也有一些坑。因此记录一下。

github:https://github.com/resilience4j/resilience4j

官方文档:https://resilience4j.readme.io/docs/circuitbreaker

我使用的是resilience4j 最新版本 0.16.0,spring boot 2.1.6。

相关依赖

<dependencies>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-actuator</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

  <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-aop</artifactId>

    </dependency>

    <dependency>

        <groupId>io.github.resilience4j</groupId>

        <artifactId>resilience4j-spring-boot2</artifactId>

        <version>0.16.0</version>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-test</artifactId>

        <scope>test</scope>

    </dependency>

</dependencies>

配置resilience4j,在spring 中的application.yml 中增加如下配置:

resilience4j.circuitbreaker:

instances:

backendA:

  registerHealthIndicator: true

  ringBufferSizeInClosedState: 10

  ringBufferSizeInHalfOpenState: 3

  waitDurationInOpenState: 10s

  failureRateThreshold: 50

  eventConsumerBufferSize: 2

backendB:

  registerHealthIndicator: true

  ringBufferSizeInClosedState: 10

  ringBufferSizeInHalfOpenState: 3

  waitDurationInOpenState: 10s

  failureRateThreshold: 50

  eventConsumerBufferSize: 2

recordFailurePredicate: io.github.robwin.exception.RecordFailurePredicate

resilience4j.retry:

instances:

backendA:

  maxRetryAttempts: 3

  waitDuration: 10s

  enableExponentialBackoff: true

  exponentialBackoffMultiplier: 2

  retryExceptions:

    - org.springframework.web.client.HttpServerErrorException

  ignoreExceptions:

    - com.learn.demo.resilience.ResilienceException

    - java.io.IOException

backendB:

  maxRetryAttempts: 3

  waitDuration: 10s

  retryExceptions:

    - com.learn.demo.resilience.ResilienceException

  ignoreExceptions:

    - java.io.IOException

resilience4j.bulkhead:

instances:

backendA:

  maxConcurrentCall: 10

  maxWaitDuration: 20ms

backendB:

  maxWaitDuration: 10ms

  maxConcurrentCall: 20

resilience4j.thread-pool-bulkhead:

instances:

backendC:

  threadPoolProperties:

    maxThreadPoolSize: 1

    coreThreadPoolSize: 1

    queueCapacity: 1

resilience4j.ratelimiter:

instances:

backendA:

  limitForPeriod: 10

  limitRefreshPeriod: 1s

  timeoutDuration: 0

  registerHealthIndicator: true

  eventConsumerBufferSize: 100

backendB:

  limitForPeriod: 6

  limitRefreshPeriod: 500ms

  timeoutDuration: 3s

server:

port: 9090

注意

resilience4j 的配置在0.16.0 发生了一下变化。网上一些文档都是基于0.13.0版本。还有0.16.0版本配置不能被IDEA 识别,也不能自动联想,所以使用0.16.0版本尽量参考官网的配置。

熔断

配置介绍

配置 默认值 描述
failureRateThreshold 50 故障率阈值(百分比),超过该阈值,CircuitBreaker 触发熔断
ringBufferSizeInHalfOpenState10CircuitBreaker 半开时环形缓冲区的大小。当CircuitBreaker从断开状态转换为半开状态,使用此环形缓冲器以确定是否健康。
ringBufferSizeInClosedState 100 CircuitBreaker关闭时环形缓冲区的大小,在计算故障率之前,需要填充环形缓冲区。
waitDurationInOpenState 60s CircuitBreaker在从open打开到半打开之前应该等待的时间。
automaticTransitionFromOpenToHalfOpenEnabled false 是否自动有open 切换到half open
recordExceptions null 失败异常
ignoreExceptions null 需要忽略的异常
recordFailure throwable -> true 自定义失败判定条件函数,默认所有异常都为失败

注解

@CircuitBreaker(name = "backendA")

code

@Retry(name = "backendA")

@CircuitBreaker(name = "backendA")

@RateLimiter(name = "backendA")

@Service

public class ServiceA {

@Bulkhead(name = "backendA")

public String sucess(){

    System.out.println("sucess a");

    return "sucess a";

}

@Bulkhead(name = "backendA")

public String fail() throws ResilienceException {

    throw new ResilienceException("fail a");

}

}

多次失败达到阈值之后,再调用会抛出异常

io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'backendA' is OPEN and does not permit further calls

rest 调用返回结果:

{

"timestamp": "2019-07-10T09:45:21.065+0000",

"status": 500,

"error": "Internal Server Error",

"message": "CircuitBreaker 'backendA' is OPEN and does not permit further calls",

"path": "/serviceA/failed"

}

这种情况可以配合spring aop,拦截异常,返回特性http 状态码或者信息,让前端捕获特定http 状态码,以此来呈现熔断之后的ui。

限流

配置

配置 默认值 描述
timeoutDuration 5s 线程等待时间
limitRefreshPeriod 500ns 令牌刷新周期
limitForPeriod 50 一个周期内令牌数

注解

@RateLimiter(name = "backendA")

code

同上

达到限制时抛出异常

io.github.resilience4j.ratelimiter.RequestNotPermitted: RateLimiter 'backendA' does not permit further calls

注意

经过试验,当@RateLimiter和@CircuitBreaker一起使用时,需要熔断器增加忽略RequestNotPermitted异常。否则会触发熔断。

ignoreExceptions:

  • io.github.resilience4j.ratelimiter.RequestNotPermitted

隔离(bulkhead)

其主要作用是限制并发次数

配置

配置 默认值 描述
maxConcurrentCalls 25 最大并发数
maxWaitDuration 0 饱和时等待时间

注解

@Bulkhead(name = "backendA")

重试

配置

配置 默认值 描述
maxAttempts 3 最大尝试次数
waitDuration 500ms 等待间隔
intervalFunction numOfAttempts - > waitDuration 故障后等待时间函数,默认为waitDuration,也可以通过函数修改为指数增长
retryOnResultPredicate 判断结果是否重试Predicate
retryOnExceptionPredicate 判断异常是否重试Predicate
retryExceptions 重试异常列表
ignoreExceptions 忽略异常列表

注解

@Retry(name = "backendA")

resilience4j 为我们提供了很棒的容错库,简单易用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容