标签: resilience4j

将 HystrixCommands 迁移到 Resilience4j

鉴于 Hystrix 进入维护模式,我一直致力于将(相当大的)代码库迁移到 Resilience4j。

我在 Hystrix 中大量使用以下模式:

new HystrixCommand<SomeReturnValue>(DependencyKeys.DEPENDENCY) {
    @Override
    protected SomeReturnValue run() {
        return someExpensiveCall();
    }
}
    .observe()
Run Code Online (Sandbox Code Playgroud)

我想用 Resilience4j 复制 Hystrix 的一些功能。

到目前为止,我有以下语法来连接外部调用:

resilience.single(DependencyKeys.DEPENDENCY, this::someExpensiveCall);
Run Code Online (Sandbox Code Playgroud)

其中Resilience类提供single方法:

public <T> Single<T> single(ResilienceKey key, Callable<T> callable) {
    return Completable.complete()
            .subscribeOn(Schedulers.computation())
            .observeOn(configuration.scheduler(key))
            .andThen(Single.defer(() -> Single.fromCallable(callable)
                    .lift(CircuitBreakerOperator.of(configuration.circuitBreaker(key)))
                    .lift(RateLimiterOperator.of(configuration.rateLimiter(key)))
                    .lift(BulkheadOperator.of(configuration.bulkhead(key)))
            ))
            .observeOn(Schedulers.computation());
}
Run Code Online (Sandbox Code Playgroud)

在断路和在不同线程池上运行代码方面,这看起来如何更好地类似于 Hystrix,但以更理智的方式。我真的不喜欢用 just 来启动链,这样我就可以在实际的可调用对象被包装之前Completable.complete()强制使用 a 。observeOn

java reactive-programming hystrix rx-java2 resilience4j

6
推荐指数
1
解决办法
3543
查看次数

滑动窗口大小与最小调用次数的区别

我是断路器的新手,最近在我的一项服务中实现了它们。我正在浏览Resilience 4J 官方文档,发现我们可以为断路器配置两个属性。

  1. 滑动窗口大小
  2. 最小呼叫次数

上述两个属性都指定必须对服务进行的调用次数,以确定断路器是否应保持打开状态或应关闭状态。我需要了解这两个属性之间的细微差别以及它们之间可能存在的任何关系?它们应该相互独立配置还是两者之间应该存在关系?

另外,以上两者之间是否有关系permittedNumberOfCallsInHalfOpenState。例如,如果我配置permittedNumberOfCallsInHalfOpenState为 5,但我的slidingWindowSize/minimumNumberOfCalls配置为 10,那么如何重新验证断路器状态?因为它至少需要 10 个请求才能重新评估断路器的新状态,但当它处于打开状态时我们只允许 5 个请求?

circuit-breaker spring-boot resilience4j

6
推荐指数
1
解决办法
9062
查看次数

Resilience4j和弹簧执行器-开路停电服务

我在Spring Boot项目中添加了以下依赖项

implementation 'io.github.resilience4j:resilience4j-spring-boot2:0.14.1'
Run Code Online (Sandbox Code Playgroud)

当断路器断开时,我在执行器/运行状况端点上收到以下响应,状态代码为503 Service Unavailable:

{
"status": "DOWN",
"details": {
    "diskSpace": {
        "status": "UP",
        "details": {
            "total": 499963174912,
            "free": 432263229440,
            "threshold": 10485760
        }
    },
    "refreshScope": {
        "status": "UP"
    },
    "getFlightInfoCircuitBreaker": {
        "status": "DOWN",
        "details": {
            "failureRate": "100.0%",
            "failureRateThreshold": "2.0%",
            "maxBufferedCalls": 1,
            "bufferedCalls": 1,
            "failedCalls": 1,
            "notPermittedCalls": 1,
            "state": "OPEN"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

}

我的AWS ECS容器运行状况检查使用此端点来确定其运行状况,并在非200响应时重启容器。

由于我不希望在断路器打开时重新启动服务,是否有办法在不导致服务状态下降的情况下打开断路器?

我知道registerHealthIndicator: false可以解决此问题的属性,但这仍会删除执行器上的断路器统计信息,我仍然希望看到。

spring-boot-actuator resilience4j

5
推荐指数
1
解决办法
485
查看次数

运行 Spring Boot 应用程序时出现兼容版本问题,但在 pom 中只有版本

应用程序未启动,但我只添加了一个版本的resilience4j

<dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-boot2</artifactId>
            <version>1.3.1</version>
        </dependency>
Run Code Online (Sandbox Code Playgroud)

这是日志:

***************************
APPLICATION FAILED TO START
***************************

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

    io.github.resilience4j.circuitbreaker.configure.CircuitBreakerConfiguration.createCircuitBreakerRegistry(CircuitBreakerConfiguration.java:141)

The following method did not exist:

    io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry.of(Ljava/util/Map;Lio/github/resilience4j/core/registry/RegistryEventConsumer;Lio/vavr/collection/Map;)Lio/github/resilience4j/circuitbreaker/CircuitBreakerRegistry;

The method's class, io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry, is available from the following locations:

    jar:file:/Users/Smit/.m2/repository/io/github/resilience4j/resilience4j-circuitbreaker/1.1.0/resilience4j-circuitbreaker-1.1.0.jar!/io/github/resilience4j/circuitbreaker/CircuitBreakerRegistry.class

It was loaded from the following location:

    file:/Users/Smit/.m2/repository/io/github/resilience4j/resilience4j-circuitbreaker/1.1.0/resilience4j-circuitbreaker-1.1.0.jar


Action:

Correct the classpath of your application so that it contains a single, compatible version of io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry


Process finished …
Run Code Online (Sandbox Code Playgroud)

java maven spring-boot resilience4j

5
推荐指数
2
解决办法
9086
查看次数

Resilience4j 舱壁线程行为

我正在使用 Resilience4j 进行大量测试并监视线程的行为。

我使用的是 spring-boot 2.2.5,resilience4j 1.4.0。Ga特林(加载工具)、VisualVM(分析线程)

我意识到:

  1. 当我使用舱壁类型 = SEMAPHORE 时。

    我意识到异步执行将使用默认的 ExecutorService,在这种情况下,ForkJoinPool 和此配置将起作用:

    maxConcurrentCalls, maxWaitDuration 
    
    Run Code Online (Sandbox Code Playgroud)

    如果您使用的是bulkhead type = THREADPOOL,上述配置将被忽略。

  2. 当我使用批量 THREADPOOL 时,这些配置将起作用:

    maxThreadPoolSize, coreThreadPoolSize, queueCapacity, keepAliveDuration
    
    Run Code Online (Sandbox Code Playgroud)

    这些配置将被忽略:

    maxConcurrentCalls, maxWaitDuration 
    
    Run Code Online (Sandbox Code Playgroud)

我的代码:

@CircuitBreaker(name = MyServiceCommand.BEAN_NAME, fallbackMethod = "fallback")
@TimeLimiter(name = MyServiceCommand.BEAN_NAME)
@Bulkhead(name = MyServiceCommand.BEAN_NAME, type = Bulkhead.Type.THREADPOOL)
@Component
@AllArgsConstructor
@Slf4j
public class MyServiceCommand extends ResilienceAbstractCommand {

    protected static final String BEAN_NAME = "MyService";

    private SlowService slowService;

    public CompletableFuture<String> perform() {

        return CompletableFuture.completedFuture(slowService.get());
    }

    private CompletableFuture<String> fallback() {
        return CompletableFuture.completedFuture("fallback");
    } …
Run Code Online (Sandbox Code Playgroud)

spring-boot resilience4j

5
推荐指数
0
解决办法
3241
查看次数

如何将 CircuitBreaker 与 TimeLimiter 和 Bulkhead 结合使用?

我有一个通过 REST 调用依赖项的服务。服务和依赖是微服务架构的一部分,所以我想使用弹性模式。我的目标是:

  • 有一个断路器来保护它在挣扎时的依赖
  • 限制调用可以运行的时间。该服务具有 SLA,并且必须在特定时间进行响应。在超时时,我们使用回退值。
  • 限制对依赖项的并发调用数。通常调用率低,响应快,但我们希望保护依赖免受服务内部的突发和队列请求。

下面是我目前的代码。它有效,但理想情况下我想使用TimeLimiterBulkhead类,因为它们似乎可以协同工作。

我怎样才能更好地写这个?

@Component
class FooService(@Autowired val circuitBreakerRegistry: CircuitBreakerRegistry)
{
    ...

    // State machine to take load off the dependency when slow or unresponsive
    private val circuitBreaker = circuitBreakerRegistry
        .circuitBreaker("fooService")

    // Limit parallel requests to dependency
    private var semaphore = Semaphore(maxParallelRequests)

    // The protected function
    private suspend fun makeHttpCall(customerId: String): Boolean {
        val client = webClientProvider.getCachedWebClient(baseUrl)

        val response = client
            .head()
            .uri("/the/request/url")
            .awaitExchange()

        return when (val status = response.rawStatusCode()) { …
Run Code Online (Sandbox Code Playgroud)

spring-boot spring-webflux resilience4j kotlin-coroutines

5
推荐指数
1
解决办法
1071
查看次数

调用不会调用 Resilience4 断路器的后备方法

我正在使用 Resilience4j 断路器版本:'1.4.0 和 Spring boot 版本 2.0.6,我的问题是 - 回退方法不起作用。该调用不会转到后备方法。下面是我的代码:

@Override
@CircuitBreaker(name="mainService",fallbackMethod = "callFallback")
public JSONObject callService(JSONObject rawRequest) throws TimeoutException {
      ...
       throw new TimeoutException("Time occured while calling 
       service");
      ...
}
Run Code Online (Sandbox Code Playgroud)

-- 和后备方法:

private JSONObject callFallback(JSONObject rawRequest,Throwable t){

    System.out.println("Inside fallback method callNsFallback, 
        cause"+t.toString());

        logger.info("Inside fallback method callFallback, 
        cause - {}",t.toString());

    return rawRequest;
}
Run Code Online (Sandbox Code Playgroud)

--application.yml中的配置

resilience4j:
circuitbreaker:
    configs:
    default:
        registerHealthIndicator: true
        ringBufferSizeInClosedState: 5
        ringBufferSizeInHalfOpenState: 3
        slidingWindowSize: 10
        minimumNumberOfCalls: 5
        permittedNumberOfCallsInHalfOpenState: 3
        automaticTransitionFromOpenToHalfOpenEnabled: true
        waitDurationInOpenState: 1s
        failureRateThreshold: 50
        eventConsumerBufferSize: 10
        recordExceptions:
        - …
Run Code Online (Sandbox Code Playgroud)

spring circuit-breaker spring-boot resilience4j

5
推荐指数
1
解决办法
3844
查看次数

使用 Spring Reactor 时为什么要使用断路器和隔板?

请帮助我找到断路器和隔板模式在 Spring Reactor 应用程序中有用的原因。

由于 Reactor 中的操作将是非阻塞的,并且这两种模式旨在节省对资源(主要是线程)的潜在影响,因此在什么情况下我可以使 Spring Reactor 应用程序中的模式受益。我此时看到的唯一一件事是,如果请求量非常大,以至于将它们保留在内存中,那么在等待超时(而不是断路器启动并回落)时,我们会运行 OOM。

circuit-breaker project-reactor resilience4j

5
推荐指数
1
解决办法
1288
查看次数

Resilience4J Retry 的预期行为是什么?

我在 Spring Boot 项目中使用 Resilience4J 来调用 REST 客户端,如下所示:

@Retry(name = "customerService")
public Customer getCustomer(String customerNumber) {
    restTemplate.exchange("https://customer-service.net", HttpMethod.GET, ..., customerNumber);
}
Run Code Online (Sandbox Code Playgroud)

使用此配置:

resilience4j.retry:
    instances:
        customerService:
            maxAttempts: 3
            waitDuration: 10s
            retryExceptions:
                - org.springframework.web.client.HttpServerErrorException
Run Code Online (Sandbox Code Playgroud)

我的期望是,如果restTemplate.exchange()调用 且客户服务以 a 响应HttpServerErrorException,则该getCustomer()方法将在等待 10 秒后再调用 3 次。

然而,这种情况并非如此。

该方法不会再被调用,并且会立即抛出异常。

看到示例中包含后备方法,我决定添加它,即使我真的不想调用不同的方法,我只想再次调用我的原始方法。

无论如何,我指定了一个回退:

@Retry(name = "customerService", fallback = "customerFb")
public Customer getCustomer(String customerNumber) {
    return getCustomer();
}

private Customer customerFb(String customerNumber, HttpServerErrorException ex) {
    log.error("Could not retrieve customer... retrying...");
    return getCustomer();
}

private …
Run Code Online (Sandbox Code Playgroud)

java spring spring-boot resilience4j resilience4j-retry

5
推荐指数
1
解决办法
1万
查看次数

在 Resilience4j 中集成断路器、重试和时间限制器

我正在尝试使用Resilience4j功能。

我的用例是将这 3 个模块结合起来:

  • 断路器
  • 重试
  • 时间限制器

我想组合所有这些模块并仅执行该方法一次

代码

这是我尝试过的。

Supplier<R> supplier = this::doSomething;

timeLimiter.executeFutureSupplier(() -> CompletableFuture.supplyAsync(supplier));

return Decorators.ofSupplier(supplier)
                .withCircuitBreaker(circuitBreaker)
                .withRetry(retry)
                .withBulkhead(bulkhead)
                .decorate();
Run Code Online (Sandbox Code Playgroud)

问题

我的doSomething()方法执行了两次,而不是预期的一次。

有人之前见过这个问题吗?

execution circuit-breaker time-limiting resilience4j resilience4j-retry

4
推荐指数
1
解决办法
4041
查看次数