6 个版本 (3 个稳定版本)
1.1.1 | 2024 年 2 月 11 日 |
---|---|
1.1.0 | 2022 年 7 月 27 日 |
1.0.0 | 2021 年 8 月 9 日 |
0.3.0 | 2020 年 9 月 22 日 |
0.1.0 | 2019 年 7 月 3 日 |
#68 in 并发
12,877 每月下载量
25KB
529 行
recloser ┃
使用环形缓冲区实现的并发 电路断路器。
Recloser
结构体提供了一个 call(...)
方法,用于封装可能失败的功能调用。当达到某些 failure_rate
时,它将积极拒绝这些调用,并在一段时间后再次允许它们。通过 AsyncRecloser
包装器,也提供了 call(...)
的未来感知版本。
API 主要基于 failsafe 和 resilient4j 的环形缓冲区实现。
使用方法
Recloser
可以处于三种状态
State::Closed(RingBuffer(len))
:初始的Recloser
状态。在基于调用次数计算failure_rate
之前,至少需要执行len
次调用。在此之后,可能会发生从State::Closed(_)
状态到State::Open(_)
状态的转换。State::Open(duration)
:在duration
过去之前,所有调用都将返回Err(Error::Rejected)
,然后发生从State::Open(_)
状态到State::HalfOpen(_)
状态的转换。State::HalfOpen(RingBuffer(len))
:在根据它计算failure_rate
之前,至少需要执行len
次调用。基于这个计算结果,状态将转换到State::Closed(_)
或State::Open(_)
状态。
状态转换设置可以按以下方式自定义
use std::time::Duration;
use recloser::Recloser;
// Equivalent to Recloser::default()
let recloser = Recloser::custom()
.error_rate(0.5)
.closed_len(100)
.half_open_len(10)
.open_wait(Duration::from_secs(30))
.build();
将危险函数调用包装起来以控制故障传播
use recloser::{Recloser, Error};
// Performs 1 call before calculating failure_rate
let recloser = Recloser::custom().closed_len(1).build();
let f1 = || Err::<(), usize>(1);
// First call, just recorded as an error
let res = recloser.call(f1);
assert!(matches!(res, Err(Error::Inner(1))));
// Now also computes failure_rate, that is 100% here
// Will transition to State::Open afterward
let res = recloser.call(f1);
assert!(matches!(res, Err(Error::Inner(1))));
let f2 = || Err::<(), i64>(-1);
// All calls are rejected (while in State::Open)
let res = recloser.call(f2);
assert!(matches!(res, Err(Error::Rejected)));
还可以根据调用丢弃一些错误。这种行为由ErrorPredicate<E>
trait控制,它已经为所有Fn(&E) -> bool
实现了。
use recloser::{Recloser, Error};
let recloser = Recloser::default();
let f = || Err::<(), usize>(1);
// Custom predicate that doesn't consider usize values as errors
let p = |_: &usize| false;
// Will not record resulting Err(1) as an error
let res = recloser.call_with(p, f);
assert!(matches!(res, Err(Error::Inner(1))));
包装返回Future
的函数需要使用一个AsyncRecloser
,它只是包装了一个普通的Recloser
。
use std::future;
use recloser::{Recloser, Error, AsyncRecloser};
let recloser = AsyncRecloser::from(Recloser::default());
let future = future::ready::<Result<(), usize>>(Err(1));
let future = recloser.call(future);
性能
Recloser
和failsafe::CircuitBreaker
的基准测试
- 单线程工作负载:相同的性能
- 多线程工作负载:
Recloser
有10倍更好的性能
recloser_simple time: [355.17 us 358.67 us 362.52 us]
failsafe_simple time: [403.47 us 406.90 us 410.29 us]
recloser_concurrent time: [668.44 us 674.26 us 680.48 us]
failsafe_concurrent time: [11.523 ms 11.613 ms 11.694 ms]
这些基准测试是在一个Intel Core i7-6700HQ @ 8x 3.5GHz
CPU上运行的。
依赖项
~0.6–1MB
~22K SLoC