io.camunda.zeebe.logstreams.impl.flowcontrol.AppenderFlowControl Maven / Gradle / Ivy
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
* one or more contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright ownership.
* Licensed under the Zeebe Community License 1.1. You may not use this file
* except in compliance with the Zeebe Community License 1.1.
*/
package io.camunda.zeebe.logstreams.impl.flowcontrol;
import com.netflix.concurrency.limits.Limiter;
import com.netflix.concurrency.limits.limit.WindowedLimit;
import io.camunda.zeebe.util.Environment;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class AppenderFlowControl {
private static final Logger LOG = LoggerFactory.getLogger(AppenderFlowControl.class);
private static final Map ALGORITHM_CFG =
Map.of("vegas", new BackpressureCfgVegas(), "gradient2", new BackpressureCfgGradient2());
private final AppendErrorHandler errorHandler;
private final Limiter limiter;
private final AppenderMetrics metrics;
public AppenderFlowControl(final AppendErrorHandler errorHandler, final AppenderMetrics metrics) {
this.errorHandler = errorHandler;
this.metrics = metrics;
limiter = configureLimiter();
}
/**
* Tries to acquire a free in-flight spot, applying backpressure as needed.
*
* @return An Optional containing a {@link InFlightAppend} if append was accepted, an empty
* Optional otherwise.
*/
public Optional tryAcquire() {
final var inFlightAppend =
limiter
.acquire(null)
.map(limiterListener -> new InFlightAppend(errorHandler, limiterListener, metrics));
if (inFlightAppend.isEmpty()) {
metrics.increaseDeferredAppends();
LOG.trace("Skipping append due to backpressure");
}
return inFlightAppend;
}
private Limiter configureLimiter() {
final var env = new Environment();
final boolean isBackpressureEnabled =
env.getBool(BackpressureConstants.ENV_BP_APPENDER).orElse(true);
if (!isBackpressureEnabled) {
return new NoopLimiter(metrics);
}
final var algorithmName =
env.get(BackpressureConstants.ENV_BP_APPENDER_ALGORITHM).orElse("vegas").toLowerCase();
final var algorithmCfg = ALGORITHM_CFG.getOrDefault(algorithmName, new BackpressureCfgVegas());
algorithmCfg.applyEnvironment(env);
final var abstractLimit = algorithmCfg.get();
final var windowedLimiter =
env.getBool(BackpressureConstants.ENV_BP_APPENDER_WINDOWED).orElse(false);
LOG.debug(
"Configured log appender back pressure as {}. Window limiting is {}",
algorithmCfg,
windowedLimiter ? "enabled" : "disabled");
return AppendLimiter.builder()
.limit(windowedLimiter ? WindowedLimit.newBuilder().build(abstractLimit) : abstractLimit)
.metrics(metrics)
.build();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy