A Spring Boot application that simulates a slow/unreliable downstream dependency service for demonstrating thread pool exhaustion scenarios.
This application serves as a controlled downstream dependency that can toggle between FAST (healthy) and SLOW (unhealthy/timing-out) modes. It's designed to help demonstrate how a slow, timing-out downstream service can exhaust the primary application's request thread pool, causing complete application-wide failure.
- âś… Configurable Behavior: Toggle between FAST and SLOW modes via REST API
- âś… Automatic State Toggle: Script to automatically switch states at configurable intervals
- âś… Realistic Simulation: Simulates network timeouts without returning responses in SLOW mode
- âś… Comprehensive Logging: Detailed logging of all requests and state changes
- âś… Thread-Safe: Uses atomic operations for state management
- âś… Spring Boot Actuator: Health checks and metrics endpoints
- âś… Java 8 Compatible: Built with Spring Boot 2.7.x
Port: 8091
Default State: FAST
Slow Mode Delay: 30,000ms (30 seconds) - configurable in application.yml
server:
port: 8091
app:
slow-mode-delay: 30000 # Delay in milliseconds for SLOW mode
default-state: FAST # Initial state: FAST or SLOWGET /api/data
This is the endpoint that CoreService will call. Behavior depends on current state:
FAST Mode:
- Returns immediately with success response
- Response time: ~1-10ms
SLOW Mode:
- Sleeps for 30 seconds (configurable)
- Client will timeout before receiving response
- Simulates a completely unresponsive service
Response Example (FAST mode):
{
"status": "OK",
"message": "Data retrieved successfully",
"timestamp": "2025-11-10T14:30:45.123",
"serviceState": "FAST"
}GET /_config/state
Query the current service state.
Response Example:
{
"currentState": "FAST",
"message": "Current service state",
"timestamp": "2025-11-10T14:30:45.123",
"slowModeDelayMs": 30000
}POST /_config/state
Change the service behavior mode.
Request Body:
{
"state": "SLOW"
}Valid states: FAST, SLOW
Response Example:
{
"currentState": "SLOW",
"message": "Service state successfully changed to SLOW",
"timestamp": "2025-11-10T14:30:45.123",
"slowModeDelayMs": 30000
}POST /_config/state/fast - Immediately switch to FAST mode
POST /_config/state/slow - Immediately switch to SLOW mode
GET /api/stats
Returns request count and current state.
Response Example:
Total requests processed: 42 | Current state: SLOW
GET /actuator/health
Spring Boot Actuator health endpoint.
- Java 8 or higher
- Maven 3.6+
mvn clean packagemvn spring-boot:runOr run the JAR directly:
java -jar target/slow-dependency-service-1.0.0.jarOverride configuration via command line:
java -jar target/slow-dependency-service-1.0.0.jar \
--server.port=8092 \
--app.slow-mode-delay=45000 \
--app.default-state=SLOW-
Ensure service is in FAST mode:
curl http://localhost:8091/_config/state
-
Test the data endpoint:
curl http://localhost:8091/api/data
Expected: Immediate response with
status: "OK"
-
Switch to SLOW mode:
curl -X POST http://localhost:8091/_config/state \ -H "Content-Type: application/json" \ -d '{"state": "SLOW"}'
-
Test the data endpoint:
curl http://localhost:8091/api/data
Expected: Request hangs for 30 seconds (or until client timeout)
- Start SlowDependencyService (this app) on port 8091
- Start CoreService on port 8090 (configured to call this service)
- Put SlowDependencyService in SLOW mode
- Send multiple concurrent requests to CoreService
- Observe CoreService thread pool exhaustion
With curl (multiple requests):
# Terminal 1-10: Simulate concurrent requests
for i in {1..10}; do
(curl http://localhost:8090/api/some-endpoint &)
done-
While in SLOW mode causing issues, switch back to FAST:
curl -X POST http://localhost:8091/_config/state/fast
-
Verify service recovers:
curl http://localhost:8091/api/data
For long-running tests or demonstrations, use the automatic state toggle script:
# Toggle state every 30 minutes (default)
./toggle-state.sh 30
# Toggle state every 60 minutes (1 hour)
./toggle-state.sh 60
# Toggle state every 5 minutes (for testing)
./toggle-state.sh 5The script will:
- Check if the service is running
- Display current state
- Automatically toggle between SLOW and FAST at the specified interval
- Log all state changes with timestamps
- Can be stopped with Ctrl+C
Example output:
======================================================================
SlowDependencyService - Automatic State Toggle
======================================================================
Service URL: http://localhost:8091
Toggle Interval: 30 minutes (1800 seconds)
Start Time: 2025-11-10 15:30:00
======================================================================
[INFO] 2025-11-10 15:30:00 - Checking if SlowDependencyService is running...
[SUCCESS] 2025-11-10 15:30:00 - Service is running
[INFO] 2025-11-10 15:30:00 - Initial state: FAST
[INFO] 2025-11-10 15:30:00 - Starting automatic state toggle...
[INFO] 2025-11-10 15:30:00 - Next toggle scheduled at: 2025-11-10 16:00:00
- Console: Colored output with all application logs
- logs/slow-dependency-service.log: All application logs (rolling daily)
- logs/requests.log: Request-specific logs only (rolling daily)
com.example.slowdependency: DEBUGorg.springframework.web: INFO- Root: INFO
FAST Mode Request:
2025-11-10 14:30:45.123 [http-nio-8091-exec-1] DEBUG c.e.s.controller.DataController - ==> [Request #1] Received on thread: http-nio-8091-exec-1 | Current State: FAST
2025-11-10 14:30:45.125 [http-nio-8091-exec-1] DEBUG c.e.s.service.ServiceStateManager - FAST mode active - No delay
2025-11-10 14:30:45.126 [http-nio-8091-exec-1] DEBUG c.e.s.controller.DataController - <== [Request #1] Responding on thread: http-nio-8091-exec-1 | State: FAST | Status: OK
SLOW Mode Request:
2025-11-10 14:32:10.234 [http-nio-8091-exec-2] DEBUG c.e.s.controller.DataController - ==> [Request #2] Received on thread: http-nio-8091-exec-2 | Current State: SLOW
2025-11-10 14:32:10.235 [http-nio-8091-exec-2] WARN c.e.s.service.ServiceStateManager - SLOW mode active - Thread http-nio-8091-exec-2 will sleep for 30000ms
... (30 seconds later)
2025-11-10 14:32:40.236 [http-nio-8091-exec-2] WARN c.e.s.service.ServiceStateManager - SLOW mode - Thread http-nio-8091-exec-2 woke up after 30000ms
2025-11-10 14:32:40.237 [http-nio-8091-exec-2] DEBUG c.e.s.controller.DataController - <== [Request #2] Responding on thread: http-nio-8091-exec-2 | State: SLOW | Status: OK
State Change:
2025-11-10 14:31:00.567 [http-nio-8091-exec-3] INFO c.e.s.controller.ConfigController - State change request received: SLOW
2025-11-10 14:31:00.568 [http-nio-8091-exec-3] INFO c.e.s.service.ServiceStateManager - Service state changed: FAST -> SLOW
2025-11-10 14:31:00.569 [http-nio-8091-exec-3] INFO c.e.s.controller.ConfigController - State change successful: SLOW
- ServiceStateManager: Thread-safe state management using
AtomicReference - DataController: Main endpoint that simulates downstream service
- ConfigController: Administrative endpoints for state control
- Model Classes: DTOs for requests and responses
[FAST Mode] --> POST /_config/state {"state":"SLOW"} --> [SLOW Mode]
|
[FAST Mode] <-- POST /_config/state {"state":"FAST"} <--------+
FAST Mode:
- Request thread handles request immediately
- Returns response in milliseconds
- Thread released back to pool
SLOW Mode:
- Request thread enters
Thread.sleep(30000) - Thread blocked for entire duration
- If multiple requests arrive, multiple threads get blocked
- Eventually exhausts thread pool
CoreService should be configured to call this service's /api/data endpoint:
// In CoreService configuration
String slowDependencyUrl = "http://localhost:8091/api/data";Ensure CoreService's read timeout is less than this service's slow-mode delay (e.g., 10-15 seconds timeout vs 30 seconds delay).
# Check what's using port 8091
lsof -i :8091
# Kill the process or change port in application.ymlThe application automatically creates the logs/ directory. Ensure write permissions.
Check logs for errors. Verify request format:
curl -X POST http://localhost:8091/_config/state \
-H "Content-Type: application/json" \
-d '{"state": "SLOW"}'- Built with Spring Boot 2.7.18 (last version supporting Java 8)
- Uses Lombok for reducing boilerplate code
- Thread-safe state management with
AtomicReference - Graceful shutdown configured (20s timeout)
This is a demonstration application for educational purposes.