Updated network
This commit is contained in:
161
app_example.py
Normal file
161
app_example.py
Normal file
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Example Flask application with proper health endpoint for Nomad/Consul.
|
||||
|
||||
This template shows:
|
||||
- Health check endpoint (CRITICAL for Nomad!)
|
||||
- Graceful shutdown handling
|
||||
- Environment variable configuration
|
||||
- Logging setup
|
||||
- Error handling
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
import signal
|
||||
from datetime import datetime
|
||||
from flask import Flask, jsonify, request
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
handlers=[
|
||||
logging.StreamHandler(sys.stdout)
|
||||
]
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Create Flask app
|
||||
app = Flask(__name__)
|
||||
|
||||
# Configuration from environment
|
||||
PORT = int(os.getenv('PORT', 5000))
|
||||
APP_ENV = os.getenv('APP_ENV', 'development')
|
||||
|
||||
# Global state for graceful shutdown
|
||||
is_shutting_down = False
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
"""Main endpoint - replace with your application logic."""
|
||||
return jsonify({
|
||||
'message': 'Hello from Flask!',
|
||||
'environment': APP_ENV,
|
||||
'timestamp': datetime.utcnow().isoformat()
|
||||
})
|
||||
|
||||
|
||||
@app.route('/health')
|
||||
def health():
|
||||
"""
|
||||
Health check endpoint - CRITICAL for Nomad/Consul!
|
||||
|
||||
This endpoint is called by Consul every 10 seconds.
|
||||
If this returns non-200 status, Consul marks service as unhealthy.
|
||||
|
||||
Returns:
|
||||
200 OK: Service is healthy
|
||||
503 Service Unavailable: Service is shutting down or unhealthy
|
||||
"""
|
||||
if is_shutting_down:
|
||||
logger.warning("Health check called during shutdown")
|
||||
return jsonify({
|
||||
'status': 'shutting_down',
|
||||
'timestamp': datetime.utcnow().isoformat()
|
||||
}), 503
|
||||
|
||||
# Add your health checks here
|
||||
health_status = {
|
||||
'status': 'healthy',
|
||||
'timestamp': datetime.utcnow().isoformat(),
|
||||
'environment': APP_ENV,
|
||||
'checks': {
|
||||
'app': 'ok',
|
||||
# Add more checks as needed:
|
||||
# 'database': check_database(),
|
||||
# 'cache': check_cache(),
|
||||
}
|
||||
}
|
||||
|
||||
return jsonify(health_status), 200
|
||||
|
||||
|
||||
@app.route('/ready')
|
||||
def ready():
|
||||
"""
|
||||
Readiness check endpoint (optional).
|
||||
|
||||
Use this for more complex readiness checks (DB connections, etc.)
|
||||
Nomad can use this as additional check.
|
||||
"""
|
||||
return jsonify({
|
||||
'ready': True,
|
||||
'timestamp': datetime.utcnow().isoformat()
|
||||
}), 200
|
||||
|
||||
|
||||
@app.route('/metrics')
|
||||
def metrics():
|
||||
"""
|
||||
Metrics endpoint for monitoring (optional).
|
||||
|
||||
Can be scraped by Prometheus if you set it up.
|
||||
"""
|
||||
# Example basic metrics
|
||||
return jsonify({
|
||||
'requests_total': 0, # Implement counter
|
||||
'uptime_seconds': 0, # Implement uptime tracking
|
||||
'timestamp': datetime.utcnow().isoformat()
|
||||
}), 200
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def not_found(error):
|
||||
"""Handle 404 errors."""
|
||||
return jsonify({'error': 'Not found'}), 404
|
||||
|
||||
|
||||
@app.errorhandler(500)
|
||||
def internal_error(error):
|
||||
"""Handle 500 errors."""
|
||||
logger.error(f"Internal error: {error}")
|
||||
return jsonify({'error': 'Internal server error'}), 500
|
||||
|
||||
|
||||
def shutdown_handler(signum, frame):
|
||||
"""
|
||||
Handle shutdown signals gracefully.
|
||||
|
||||
When Nomad stops the job, it sends SIGTERM.
|
||||
This gives the app time to finish current requests.
|
||||
"""
|
||||
global is_shutting_down
|
||||
logger.info(f"Received signal {signum}, initiating graceful shutdown...")
|
||||
is_shutting_down = True
|
||||
|
||||
# Perform cleanup here
|
||||
# - Close database connections
|
||||
# - Finish pending requests
|
||||
# - Save state if needed
|
||||
|
||||
logger.info("Cleanup complete, exiting...")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
# Register signal handlers
|
||||
signal.signal(signal.SIGTERM, shutdown_handler)
|
||||
signal.signal(signal.SIGINT, shutdown_handler)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logger.info(f"Starting Flask app on port {PORT} in {APP_ENV} mode")
|
||||
|
||||
# Run Flask app
|
||||
app.run(
|
||||
host='0.0.0.0',
|
||||
port=PORT,
|
||||
debug=(APP_ENV == 'development')
|
||||
)
|
||||
Reference in New Issue
Block a user