Implementing a Readiness Probe in Go
Readiness probes are crucial for ensuring that your Go applications are ready to receive traffic. They allow orchestration platforms like Kubernetes to determine if a pod is healthy and can handle requests, preventing traffic from being routed to unhealthy instances. This challenge asks you to implement a simple readiness probe endpoint in a Go HTTP server.
Problem Description
You need to create a Go program that exposes an HTTP endpoint (/ready) which acts as a readiness probe. This endpoint should return a 200 OK status code if the application is considered "ready" and a 503 Service Unavailable status code if it's not. Initially, the application should not be ready. The application should become ready after a configurable delay (specified in seconds). The readiness probe should also incorporate a simple health check: it should return a 503 if a simulated external dependency (represented by a simple counter) is unavailable.
Key Requirements:
/readyEndpoint: Implement an HTTP endpoint at/ready.- Initial Unready State: The application should start in an unready state.
- Delayed Readiness: The application should transition to a ready state after a specified delay.
- Dependency Health Check: The readiness probe should check the status of a simulated external dependency (a counter). If the counter is below a certain threshold, the probe should return 503.
- HTTP Status Codes: Return 200 OK for ready, 503 Service Unavailable for unready or dependency issues.
- Configurable Delay: The delay before the application becomes ready should be configurable via an environment variable (e.g.,
READINESS_DELAY). Default to 5 seconds if the environment variable is not set.
Expected Behavior:
- When the application starts, the
/readyendpoint should return a 503 Service Unavailable. - After the configured delay, the
/readyendpoint should return a 200 OK if the dependency check passes. - If the dependency check fails (counter below threshold), the
/readyendpoint should return a 503 Service Unavailable, even after the delay. - The application should continue to return 200 OK as long as the dependency check passes.
Examples
Example 1:
Input: Application starts, environment variable `READINESS_DELAY` is not set.
Output: HTTP 503 Service Unavailable when accessing /ready.
Explanation: The application starts in an unready state and the default delay of 5 seconds is applied.
Example 2:
Input: Application starts, `READINESS_DELAY` is set to 2 seconds, dependency counter is 10.
Output: HTTP 503 Service Unavailable for 2 seconds. After 2 seconds, HTTP 200 OK when accessing /ready.
Explanation: The application waits for 2 seconds before checking readiness. The dependency check passes, so 200 OK is returned.
Example 3: (Edge Case)
Input: Application starts, `READINESS_DELAY` is set to 3 seconds, dependency counter is 2.
Output: HTTP 503 Service Unavailable for 3 seconds. After 3 seconds, HTTP 503 Service Unavailable when accessing /ready.
Explanation: The application waits for 3 seconds. The dependency check fails (counter < 5), so 503 is returned.
Constraints
- Delay Range:
READINESS_DELAYshould be a positive integer. Invalid values should be treated as if the environment variable wasn't set (default to 5 seconds). - Dependency Threshold: The dependency counter threshold is 5.
- Error Handling: Handle potential errors when parsing the
READINESS_DELAYenvironment variable gracefully. - Concurrency: The readiness check should be performed sequentially, not concurrently.
- Timeouts: No explicit timeouts are required for the readiness check itself.
Notes
- Use the
time.Sleep()function to implement the delay. - Consider using the
ospackage to access environment variables. - The dependency check is a simplified simulation. In a real-world scenario, this would involve checking the status of a database, external API, or other service.
- Focus on the core logic of the readiness probe. Error handling and logging can be kept minimal for this exercise.
- The counter is a global variable for simplicity. In a production environment, consider a more robust mechanism for managing dependencies.