doc: 阅读Bulkhead文档
This commit is contained in:
@@ -309,4 +309,258 @@ CircuitBreaker circuitBreakerWithCustomConfig = circuitBreakerRegistry
|
|||||||
.circuitBreaker("name2", circuitBreakerConfig);
|
.circuitBreaker("name2", circuitBreakerConfig);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
除此之外,还可以在circuitRegistry中添加配置,该配置可以被多个CircuitBreaker实例共享
|
||||||
|
```java
|
||||||
|
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
|
||||||
|
.failureRateThreshold(70)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
circuitBreakerRegistry.addConfiguration("someSharedConfig", config);
|
||||||
|
|
||||||
|
CircuitBreaker circuitBreaker = circuitBreakerRegistry
|
||||||
|
.circuitBreaker("name", "someSharedConfig");
|
||||||
|
```
|
||||||
|
|
||||||
|
并且,可以针对默认配置进行overwrite
|
||||||
|
```java
|
||||||
|
CircuitBreakerConfig defaultConfig = circuitBreakerRegistry
|
||||||
|
.getDefaultConfig();
|
||||||
|
|
||||||
|
CircuitBreakerConfig overwrittenConfig = CircuitBreakerConfig
|
||||||
|
.from(defaultConfig)
|
||||||
|
.waitDurationInOpenState(Duration.ofSeconds(20))
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
如果不想使用CircuitBreakerRegistry来管理CircuitBreaker实例,也可以自己直接创建CircuitBreaker实例:
|
||||||
|
```java
|
||||||
|
// Create a custom configuration for a CircuitBreaker
|
||||||
|
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
|
||||||
|
.recordExceptions(IOException.class, TimeoutException.class)
|
||||||
|
.ignoreExceptions(BusinessException.class, OtherBusinessException.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CircuitBreaker customCircuitBreaker = CircuitBreaker
|
||||||
|
.of("testName", circuitBreakerConfig);
|
||||||
|
```
|
||||||
|
|
||||||
|
如果想要plugin in自己的registry实现,可以提供一个自定义的`RegistryStore`实现,并且通过Builder方法来plug in
|
||||||
|
```java
|
||||||
|
CircuitBreakerRegistry registry = CircuitBreakerRegistry.custom()
|
||||||
|
.withRegistryStore(new YourRegistryStoreImplementation())
|
||||||
|
.withCircuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Decorate and execute a functional interface
|
||||||
|
CircuitBreaker可以针对`callable, supplier, runnable, consumer, checkedrunnable, checkedsupplier, checkedconsumer, completionStage`来进行decorate。
|
||||||
|
|
||||||
|
可以通过`Try.of`或`Try.run`来调用decorated function,这样允许链式调用,使用示例如下:
|
||||||
|
```java
|
||||||
|
// Given
|
||||||
|
CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("testName");
|
||||||
|
|
||||||
|
// When I decorate my function
|
||||||
|
CheckedFunction0<String> decoratedSupplier = CircuitBreaker
|
||||||
|
.decorateCheckedSupplier(circuitBreaker, () -> "This can be any method which returns: 'Hello");
|
||||||
|
|
||||||
|
// and chain an other function with map
|
||||||
|
Try<String> result = Try.of(decoratedSupplier)
|
||||||
|
.map(value -> value + " world'");
|
||||||
|
|
||||||
|
// Then the Try Monad returns a Success<String>, if all functions ran successfully.
|
||||||
|
assertThat(result.isSuccess()).isTrue();
|
||||||
|
assertThat(result.get()).isEqualTo("This can be any method which returns: 'Hello world'");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Consume emitted RegistryEvents
|
||||||
|
可以向CircuitBreakerRegistry注册一个event consumer,并且在`CircuitBreaker`被创建、替换、删除时执行对应的action
|
||||||
|
```java
|
||||||
|
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
|
||||||
|
circuitBreakerRegistry.getEventPublisher()
|
||||||
|
.onEntryAdded(entryAddedEvent -> {
|
||||||
|
CircuitBreaker addedCircuitBreaker = entryAddedEvent.getAddedEntry();
|
||||||
|
LOG.info("CircuitBreaker {} added", addedCircuitBreaker.getName());
|
||||||
|
})
|
||||||
|
.onEntryRemoved(entryRemovedEvent -> {
|
||||||
|
CircuitBreaker removedCircuitBreaker = entryRemovedEvent.getRemovedEntry();
|
||||||
|
LOG.info("CircuitBreaker {} removed", removedCircuitBreaker.getName());
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### consume emitted CircuitBreakerEvents
|
||||||
|
CircuitBreakerEvent在如下场景下会被发出:
|
||||||
|
- state transition
|
||||||
|
- circuit breaker reset
|
||||||
|
- successful call
|
||||||
|
- recorded error
|
||||||
|
- ignored error
|
||||||
|
|
||||||
|
所有的event都包含额外的信息,例如事件创建时间、call的处理时长等。如果想要消费该类事件,需要向CircuitBreaker注册事件:
|
||||||
|
```java
|
||||||
|
circuitBreaker.getEventPublisher()
|
||||||
|
.onSuccess(event -> logger.info(...))
|
||||||
|
.onError(event -> logger.info(...))
|
||||||
|
.onIgnoredError(event -> logger.info(...))
|
||||||
|
.onReset(event -> logger.info(...))
|
||||||
|
.onStateTransition(event -> logger.info(...));
|
||||||
|
// Or if you want to register a consumer listening
|
||||||
|
// to all events, you can do:
|
||||||
|
circuitBreaker.getEventPublisher()
|
||||||
|
.onEvent(event -> logger.info(...));
|
||||||
|
```
|
||||||
|
|
||||||
|
可以使用`CircularEventConsumer`来对事件进行存储,事件会被存储在一个固定容量的circular buffer中
|
||||||
|
```java
|
||||||
|
CircularEventConsumer<CircuitBreakerEvent> ringBuffer =
|
||||||
|
new CircularEventConsumer<>(10);
|
||||||
|
circuitBreaker.getEventPublisher().onEvent(ringBuffer);
|
||||||
|
List<CircuitBreakerEvent> bufferedEvents = ringBuffer.getBufferedEvents()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bulkhead
|
||||||
|
resilence4j提供了两种bulkhead的实现,bukhead可以用于限制并发执行的数量:
|
||||||
|
- `SemaphoreBulkhead`: 该bulkhead实现基于信号量
|
||||||
|
- `FixedThreadPoolBulkhead`: 该实现使用了`a bounded queue and a fixed thread pool`
|
||||||
|
|
||||||
|
### create a BulkheadRegistry
|
||||||
|
和CircuitBreaker module类似,Bulkhead module也提供了in-memory的`BulkheadRegistry和ThreadPoolBulkheadRegistry`,用于管理Bulkhead实例,示例如下:
|
||||||
|
```java
|
||||||
|
BulkheadRegistry bulkheadRegistry = BulkheadRegistry.ofDefaults();
|
||||||
|
|
||||||
|
ThreadPoolBulkheadRegistry threadPoolBulkheadRegistry =
|
||||||
|
ThreadPoolBulkheadRegistry.ofDefaults();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create and configure a Bulkhead
|
||||||
|
可以自己提供一个全局的`BulkheadConfig`,可通过`BulkheadConfig` builder来创建config对象,该config对象支持如下属性配置:
|
||||||
|
- `maxConcurentCalls`:
|
||||||
|
- `default value`:25
|
||||||
|
- `description`:代表bulkhead允许的最大并行执行数量
|
||||||
|
- `maxWaitDuration`:
|
||||||
|
- `default value`: 0
|
||||||
|
- `description`: 代表一个线程尝试进入饱和的bulkhead时,该线程的最长等待时间
|
||||||
|
|
||||||
|
示例如下所示:
|
||||||
|
```java
|
||||||
|
// Create a custom configuration for a Bulkhead
|
||||||
|
BulkheadConfig config = BulkheadConfig.custom()
|
||||||
|
.maxConcurrentCalls(150)
|
||||||
|
.maxWaitDuration(Duration.ofMillis(500))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Create a BulkheadRegistry with a custom global configuration
|
||||||
|
BulkheadRegistry registry = BulkheadRegistry.of(config);
|
||||||
|
|
||||||
|
// Get or create a Bulkhead from the registry -
|
||||||
|
// bulkhead will be backed by the default config
|
||||||
|
Bulkhead bulkheadWithDefaultConfig = registry.bulkhead("name1");
|
||||||
|
|
||||||
|
// Get or create a Bulkhead from the registry,
|
||||||
|
// use a custom configuration when creating the bulkhead
|
||||||
|
Bulkhead bulkheadWithCustomConfig = registry.bulkhead("name2", custom);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create and configure a ThreadPoolBulkhead
|
||||||
|
可以提供一个自定义的global `ThreadPoolBulkheadConfig`,支持通过builder创建。
|
||||||
|
|
||||||
|
`ThreadPoolBulkheadConfig`支持如下配置属性:
|
||||||
|
- `maxThreadPoolSize`:
|
||||||
|
- `default value`: `Runtime.getRuntime().availableProcessors()`
|
||||||
|
- `description`: 配置线程池的最大线程数
|
||||||
|
- `coreThreadPoolSize`:
|
||||||
|
- `default value`: `Runtime.getRuntime().availableProcessors()-1`
|
||||||
|
- `description`: 配置线程池的核心线程数
|
||||||
|
- `queueCapacity`:
|
||||||
|
- `default value`: 100
|
||||||
|
- `descritpion`: 配置queue的容量
|
||||||
|
- `keepAliveDuration`:
|
||||||
|
- `default value`: 20 [ms]
|
||||||
|
- `description`: 当线程池中线程数量大于coreSize时,该值代表非核心线程在销毁前空闲的最大时长
|
||||||
|
- `writableStackTraceEnabled`:
|
||||||
|
- `default value`: true
|
||||||
|
- `descritpion`: 当bulkhead抛出异常时,是否打印除Stack Trace,当该值设置为false时,仅打印单行
|
||||||
|
|
||||||
|
```java
|
||||||
|
ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.custom()
|
||||||
|
.maxThreadPoolSize(10)
|
||||||
|
.coreThreadPoolSize(2)
|
||||||
|
.queueCapacity(20)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Create a BulkheadRegistry with a custom global configuration
|
||||||
|
ThreadPoolBulkheadRegistry registry = ThreadPoolBulkheadRegistry.of(config);
|
||||||
|
|
||||||
|
// Get or create a ThreadPoolBulkhead from the registry -
|
||||||
|
// bulkhead will be backed by the default config
|
||||||
|
ThreadPoolBulkhead bulkheadWithDefaultConfig = registry.bulkhead("name1");
|
||||||
|
|
||||||
|
// Get or create a Bulkhead from the registry,
|
||||||
|
// use a custom configuration when creating the bulkhead
|
||||||
|
ThreadPoolBulkheadConfig custom = ThreadPoolBulkheadConfig.custom()
|
||||||
|
.maxThreadPoolSize(5)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ThreadPoolBulkhead bulkheadWithCustomConfig = registry.bulkhead("name2", custom);
|
||||||
|
```
|
||||||
|
|
||||||
|
### decorate and execute a functional interface
|
||||||
|
可以使用Bulkhead对`callable, supplier, runnable, consumer, checkedrunnable, checkedsupplier, checkedconsumer, completionStage`来进行decorate,示例如下:
|
||||||
|
```java
|
||||||
|
// Given
|
||||||
|
Bulkhead bulkhead = Bulkhead.of("name", config);
|
||||||
|
|
||||||
|
// When I decorate my function
|
||||||
|
CheckedFunction0<String> decoratedSupplier = Bulkhead
|
||||||
|
.decorateCheckedSupplier(bulkhead, () -> "This can be any method which returns: 'Hello");
|
||||||
|
|
||||||
|
// and chain an other function with map
|
||||||
|
Try<String> result = Try.of(decoratedSupplier)
|
||||||
|
.map(value -> value + " world'");
|
||||||
|
|
||||||
|
// Then the Try Monad returns a Success<String>, if all functions ran successfully.
|
||||||
|
assertThat(result.isSuccess()).isTrue();
|
||||||
|
assertThat(result.get()).isEqualTo("This can be any method which returns: 'Hello world'");
|
||||||
|
assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(1);
|
||||||
|
```
|
||||||
|
```java
|
||||||
|
ThreadPoolBulkheadConfig config = ThreadPoolBulkheadConfig.custom()
|
||||||
|
.maxThreadPoolSize(10)
|
||||||
|
.coreThreadPoolSize(2)
|
||||||
|
.queueCapacity(20)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ThreadPoolBulkhead bulkhead = ThreadPoolBulkhead.of("name", config);
|
||||||
|
|
||||||
|
CompletionStage<String> supplier = ThreadPoolBulkhead
|
||||||
|
.executeSupplier(bulkhead, backendService::doSomething);
|
||||||
|
```
|
||||||
|
|
||||||
|
### consume emitted RegistryEvents
|
||||||
|
可以向`BulkheadRegistry`注册event consumer,用于监听Bulkhead的创建、替换和删除事件
|
||||||
|
```java
|
||||||
|
BulkheadRegistry registry = BulkheadRegistry.ofDefaults();
|
||||||
|
registry.getEventPublisher()
|
||||||
|
.onEntryAdded(entryAddedEvent -> {
|
||||||
|
Bulkhead addedBulkhead = entryAddedEvent.getAddedEntry();
|
||||||
|
LOG.info("Bulkhead {} added", addedBulkhead.getName());
|
||||||
|
})
|
||||||
|
.onEntryRemoved(entryRemovedEvent -> {
|
||||||
|
Bulkhead removedBulkhead = entryRemovedEvent.getRemovedEntry();
|
||||||
|
LOG.info("Bulkhead {} removed", removedBulkhead.getName());
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### consume emitted BulkheadEvents
|
||||||
|
BulkHead会发送BulkHeadEvent事件,发送的事件包含如下类型:
|
||||||
|
- permitted execution
|
||||||
|
- rejected execution
|
||||||
|
- finished execution
|
||||||
|
|
||||||
|
如果想要消费上述事件,可以按照如下示例注册event consumer
|
||||||
|
```java
|
||||||
|
bulkhead.getEventPublisher()
|
||||||
|
.onCallPermitted(event -> logger.info(...))
|
||||||
|
.onCallRejected(event -> logger.info(...))
|
||||||
|
.onCallFinished(event -> logger.info(...));
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user