8000 Provide an HTTP 503 response when the thread pool rejected the request by ahus1 · Pull Request #21963 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@
package org.keycloak.quarkus.runtime.integration.web;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.Predicate;

import org.apache.http.HttpStatus;
import org.jboss.logging.Logger;
import org.keycloak.common.ClientConnection;
import org.keycloak.common.util.Resteasy;
import org.keycloak.models.KeycloakSession;
Expand Down Expand Up @@ -46,6 +51,8 @@
*/
public class QuarkusRequestFilter implements Handler<RoutingContext>, TransactionalSessionHandler {

private final Logger logger = Logger.getLogger(QuarkusRequestFilter.class);

private final ExecutorService executor;

private Predicate<RoutingContext> contextFilter;
Expand All @@ -59,6 +66,9 @@ public QuarkusRequestFilter(Predicate<RoutingContext> contextFilter, ExecutorSer
this.executor = executor;
}

private final LongAdder rejectedRequests = new LongAdder();
private volatile boolean loadSheddingActive;

@Override
public void handle(RoutingContext context) {
if (ignoreContext(context)) {
Expand All @@ -67,7 +77,30 @@ public void handle(RoutingContext context) {
}
// our code should always be run as blocking until we don't provide a better support for running non-blocking code
// in the event loop
executor.execute(createBlockingHandler(context));
try {
executor.execute(createBlockingHandler(context));
if (loadSheddingActive) {
synchronized (rejectedRequests) {
if (loadSheddingActive) {
loadSheddingActive = false;
// rejectedRequests.sumThenReset() is approximative when concurrent increments are active, still it should be accurate enough for this log message
logger.warnf("Executor thread pool no longer exhausted, request processing continues after %s discarded request(s)", rejectedRequests.sumThenReset());
}
}
}
} catch (RejectedExecutionException e) {
if (!loadSheddingActive) {
synchronized (rejectedRequests) {
if (!loadSheddingActive) {
loadSheddingActive = true;
logger.warn("Executor thread pool exhausted, starting to reject requests");
}
}
}
rejectedRequests.increment();
// if the thread pool has been configured with a maximum queue size, it might reject the request
context.fail(HttpStatus.SC_SERVICE_UNAVAILABLE);
}
}

private boolean ignoreContext(RoutingContext context) {
Expand Down
0