Repository navigation
Resilience module: CircuitBreaker + Retry + TimeLimiter at the gateway - #1
Merged
Merged
Conversation
Add spring-cloud-starter-circuitbreaker-reactor-resilience4j dependency to api-gateway. Declare taskServiceBreaker instance with count-based sliding window (size 10, min 5 calls, 50% failure rate threshold, 10s wait duration in open state, 3 permitted calls in half-open). Wrap /tasks/** route with the CircuitBreaker filter and forward to /fallback/tasks on failure. Add FallbackController returning an RFC 7807 problem+json 503 response consistent with the platform error handling convention. End-to-end verification with Docker Compose deferred to next session. --- feat(gateway): scaffolding del circuit breaker para la ruta de task-service Añade la dependencia spring-cloud-starter-circuitbreaker-reactor- resilience4j al api-gateway. Declara la instancia taskServiceBreaker con ventana deslizante por conteo (tamaño 10, mínimo 5 llamadas, umbral de fallo del 50%, espera de 10s en estado open, 3 llamadas permitidas en half-open). Envuelve la ruta /tasks/** con el filter CircuitBreaker y redirige a /fallback/tasks en caso de fallo. Añade FallbackController que devuelve una respuesta problem+json 503 según RFC 7807, coherente con el manejo de errores del resto de la plataforma. Verificación end-to-end con Docker Compose diferida a la siguiente sesión.
Fix TaskSpecifications.byUserId to reference the flat userId column
after the monolith → microservices decomposition (was navigating
root.get("user").get("id") which no longer exists).
Refactor gateway routing config to externalise downstream URIs per
profile via placeholders (services.auth-uri, services.task-uri).
The previous approach duplicated the entire routes list between
application.yml and application-docker.yml, causing filters added
to base (like the new CircuitBreaker) to silently disappear under
the docker profile.
Enable circuit breaker health indicator at the management level
(management.health.circuitbreakers.enabled: true) and expose the
/actuator/circuitbreakers endpoint for direct observability of
breaker state, in addition to the aggregated health endpoint.
…le placeholders Documents the refactoring applied during Session 8 Part 2 of Fase 10 to eliminate the duplication of the routes list between application.yml and application-docker.yml. The pattern preserved was structural: keep routes declared once in the base file with placeholder-referenced hostnames, and let per-profile files override only the actual variance. Follows Nygard's format consistent with ADR-004.
Wraps Retry inside CircuitBreaker on the unified task-service-route. Retry configured with retries=2, methods=GET, series=SERVER_ERROR, exponential backoff (500ms firstBackoff, 1500ms maxBackoff, factor 2). Empirical verification with task-service stopped: - HTTP 503 fallback served in ~1020ms consistently - Circuit breaker sees 1 aggregated failure per client request - CircuitBreaker order=1 (outer), Retry order=2 (inner) confirmed via /actuator/gateway/routes Refs: feature/circuit-breaker branch, ADR-006 pending (TimeLimiter + ADR-006 to be added in next session)
Add resilience4j.timelimiter instance 'taskServiceBreaker' with timeoutDuration 5s and cancelRunningFuture true. This makes explicit the timeout mechanism previously acting as an invisible 1s default from Spring Cloud CircuitBreaker's integrated TimeLimiter. Empirically verified in Sesion 10: - With integrated default (1s): curl to paused downstream ~1.02s - With explicit config (5s): curl to paused downstream ~5.02s - The TimeLimiter is the dominant timeout mechanism, wrapping the entire operation including Retry attempts. Document per-route metadata timeouts as ineffective under the new spring.cloud.gateway.server.webflux prefix in SCG 2025.0.0. Kept in config with explanatory comment pointing to ADR-006 for future investigation.
- Add dedicated section 'Resilience at the gateway' summarizing CircuitBreaker + Retry + TimeLimiter composition, link to ADR-006. - Extend tech stack bullet on Spring Cloud Gateway and add Resilience4j entry. - Include /actuator/gateway/routedefinitions and /actuator/circuitbreakers in observability endpoints. - Retire Circuit Breaker from Future work (implemented); add Bulkhead pattern as deferred item conditional on fan-out routing. - Update foundation description to include resilience patterns as part of the operational core.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Complete the resilience module of Fase 10: three composable
patterns protecting
task-service-routeat the API gateway.What this PR adds
taskServiceBreaker) — count-based slidingwindow of 10 calls, opens at 50% failure rate with
min 5calls,10s in OPEN before HALF_OPEN probing.
TimeoutException, exponential backoff 500ms → 1500ms.
abstraction) — explicitly configured to 5s, overriding the
invisible 1s default.
Empirical verification
With
docker compose pause task-service:CLOSED → OPEN — the primary protection against gateway resource
exhaustion under downstream failure.
Actuator confirms state and metrics:
{ "failureRate": "80.0%", "bufferedCalls": 5, "failedCalls": 4, "notPermittedCalls": 1, "state": "OPEN" }Documentation
authentication with JWT at the gateway (context).
— externalising downstream hostnames via per-profile
placeholders (triggered by adding CircuitBreaker filter).
patterns composition, alternatives considered, empirical
verification (this module).
Notable findings documented in ADR-006
CircuitBreaker Resilience4j, invisible in config until made
explicit.
metadata.response-timeoutineffective under thenew
spring.cloud.gateway.server.webfluxprefix in SCG2025.0.0. Kept in config with explanatory comment as
documentation of the finding.
TimeLimiter (outermost, integrated) → CircuitBreaker → Retry →
HTTP call.