| from flask import Flask, redirect, request, jsonify |
| import requests |
| from threading import Lock |
| import logging |
| from datetime import datetime |
| import json |
| import os |
| import time |
|
|
| |
| logging.basicConfig( |
| level=logging.INFO, |
| format='%(asctime)s - %(levelname)s - %(message)s', |
| handlers=[ |
| logging.FileHandler('load_balancer.log'), |
| logging.StreamHandler() |
| ] |
| ) |
|
|
| app = Flask(__name__) |
|
|
| |
| SERVERS = [f"https://158.130.50.41:{port}" for port in range(7850, 7860)] |
| HEALTH_CHECK_INTERVAL = 30 |
| MAX_FAILURES = 3 |
|
|
| class LoadBalancer: |
| def __init__(self): |
| self.servers = SERVERS |
| self.current_index = 0 |
| self.lock = Lock() |
| self.server_status = {server: {'healthy': True, 'failures': 0} for server in self.servers} |
| self.last_health_check = {server: datetime.now() for server in self.servers} |
|
|
| def get_next_server(self): |
| with self.lock: |
| |
| start_index = self.current_index |
| while True: |
| server = self.servers[self.current_index] |
| if self.server_status[server]['healthy']: |
| self.current_index = (self.current_index + 1) % len(self.servers) |
| return server |
| |
| self.current_index = (self.current_index + 1) % len(self.servers) |
| if self.current_index == start_index: |
| |
| return None |
|
|
| def mark_server_failure(self, server): |
| with self.lock: |
| self.server_status[server]['failures'] += 1 |
| if self.server_status[server]['failures'] >= MAX_FAILURES: |
| self.server_status[server]['healthy'] = False |
| logging.warning(f"Server {server} marked as unhealthy") |
|
|
| def mark_server_success(self, server): |
| with self.lock: |
| self.server_status[server]['failures'] = 0 |
| self.server_status[server]['healthy'] = True |
|
|
| def health_check(self, server): |
| try: |
| |
| response = requests.get(f"{server}/health", timeout=5, verify=False) |
| if response.status_code == 200: |
| self.mark_server_success(server) |
| return True |
| else: |
| self.mark_server_failure(server) |
| return False |
| except Exception as e: |
| logging.error(f"Health check failed for {server}: {str(e)}") |
| self.mark_server_failure(server) |
| return False |
|
|
| def get_status(self): |
| return { |
| 'servers': [ |
| { |
| 'url': server, |
| 'healthy': status['healthy'], |
| 'failures': status['failures'] |
| } |
| for server, status in self.server_status.items() |
| ] |
| } |
|
|
| |
| load_balancer = LoadBalancer() |
|
|
| @app.route('/') |
| def proxy(): |
| server = load_balancer.get_next_server() |
| if not server: |
| return jsonify({'error': 'No healthy servers available'}), 503 |
| |
| |
| path = request.path |
| query_string = request.query_string.decode('utf-8') |
| |
| |
| target_url = f"{server}{path}" |
| if query_string: |
| target_url += f"?{query_string}" |
| |
| logging.info(f"Redirecting to {target_url}") |
| return redirect(target_url) |
|
|
| @app.route('/health') |
| def health(): |
| return jsonify({'status': 'healthy'}), 200 |
|
|
| @app.route('/status') |
| def status(): |
| return jsonify(load_balancer.get_status()), 200 |
|
|
| def run_health_checks(): |
| """Background task to check server health""" |
| while True: |
| for server in SERVERS: |
| load_balancer.health_check(server) |
| time.sleep(HEALTH_CHECK_INTERVAL) |
|
|
| if __name__ == '__main__': |
| |
| import threading |
| health_check_thread = threading.Thread(target=run_health_checks, daemon=True) |
| health_check_thread.start() |
| |
| |
| app.run(host='0.0.0.0', port=7860) |