trung99 commited on
Commit
615821e
·
verified ·
1 Parent(s): 85c9b6c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -0
app.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #<--BẮT ĐẦU TOÀN BỘ CODE CHO FILE load_balancer.py (WORKER ĐẦU MỐI) - PHIÊN BẢN CUỐI CÙNG-->
2
+ import os
3
+ import asyncio
4
+ import aiohttp
5
+ import random
6
+ from fastapi import FastAPI, HTTPException, Request, Header
7
+ from pydantic import BaseModel, Field
8
+ from typing import List, Dict, Any
9
+
10
+ # --- Cấu hình ---
11
+ # Đọc key xác thực bí mật từ Secrets của Hugging Face.
12
+ # Bạn cần vào Settings -> Secrets của Space này để thêm một Secret mới tên là AUTH_KEY
13
+ API_AUTH_KEY = os.getenv("AUTH_KEY", "default-secret-key-change-me")
14
+
15
+ # !!! THAY THẾ BẰNG DANH SÁCH URL WORKER THỢ THẬT CỦA BẠN !!!
16
+ WORKER_URLS = [
17
+ # Dán danh sách URL của các worker thợ vào đây. Ví dụ:
18
+ "https://whf-manager-api-key-sheet-worker-checker-01.hf.space",
19
+ "https://whf-manager-api-key-sheet-worker-checker-02.hf.space",
20
+ "https://whf-manager-api-key-sheet-worker-checker-03.hf.space",
21
+ "https://whf-manager-api-key-sheet-worker-checker-04.hf.space",
22
+ "https://whf-manager-api-key-sheet-worker-checker-05.hf.space",
23
+ "https://whf-manager-api-key-sheet-worker-checker-06.hf.space",
24
+ "https://whf-manager-api-key-sheet-worker-checker-07.hf.space",
25
+ "https://whf-manager-api-key-sheet-worker-checker-08.hf.space",
26
+ "https://whf-manager-api-key-sheet-worker-checker-09.hf.space",
27
+ "https://whf-manager-api-key-sheet-worker-checker-10.hf.space",
28
+ "https://whf-manager-api-key-sheet-worker-checker-11.hf.space",
29
+ "https://whf-manager-api-key-sheet-worker-checker-12.hf.space",
30
+ "https://whf-manager-api-key-sheet-worker-checker-13.hf.space",
31
+ "https://whf-manager-api-key-sheet-worker-checker-14.hf.space",
32
+ "https://whf-manager-api-key-sheet-worker-checker-15.hf.space",
33
+ "https://whf-manager-api-key-sheet-worker-checker-16.hf.space",
34
+ "https://whf-manager-api-key-sheet-worker-checker-17.hf.space",
35
+ "https://whf-manager-api-key-sheet-worker-checker-18.hf.space",
36
+ "https://whf-manager-api-key-sheet-worker-checker-19.hf.space",
37
+ "https://whf-manager-api-key-sheet-worker-checker-20.hf.space",
38
+ "https://whf-manager-api-key-sheet-worker-checker-21.hf.space",
39
+ "https://whf-manager-api-key-sheet-worker-checker-22.hf.space",
40
+ "https://whf-manager-api-key-sheet-worker-checker-23.hf.space",
41
+ "https://whf-manager-api-key-sheet-worker-checker-24.hf.space",
42
+ "https://whf-manager-api-key-sheet-worker-checker-25.hf.space",
43
+ "https://whf-manager-api-key-sheet-worker-checker-26.hf.space",
44
+ "https://whf-manager-api-key-sheet-worker-checker-27.hf.space",
45
+ "https://whf-manager-api-key-sheet-worker-checker-28.hf.space",
46
+ "https://whf-manager-api-key-sheet-worker-checker-29.hf.space",
47
+ "https://whf-manager-api-key-sheet-worker-checker-30.hf.space"
48
+
49
+ ]
50
+
51
+ # --- Pydantic Models ---
52
+ class APIKeyPayload(BaseModel):
53
+ api_keys: List[str] = Field(..., min_items=1)
54
+
55
+ # --- Khởi tạo ứng dụng FastAPI ---
56
+ app = FastAPI(
57
+ title="Maintenance Load Balancer (Đầu mối)",
58
+ description="Xác thực, nhận yêu cầu từ client và phân phối đến các worker thợ.",
59
+ version="2.0.0",
60
+ )
61
+
62
+ # --- Logic của Load Balancer ---
63
+ worker_load = {url: 0 for url in WORKER_URLS}
64
+ load_lock = asyncio.Lock()
65
+
66
+ async def select_worker() -> str:
67
+ if not WORKER_URLS: raise ValueError("Danh sách WORKER_URLS chưa được cấu hình!")
68
+ async with load_lock:
69
+ min_load = min(worker_load.values())
70
+ least_busy_workers = [url for url, load in worker_load.items() if load == min_load]
71
+ return random.choice(least_busy_workers)
72
+
73
+ async def forward_request_to_worker(worker_url: str, payload: Dict[str, Any], auth_key: str):
74
+ endpoint = "/check-credits" # Endpoint trên worker thợ
75
+ target_url = f"{worker_url.rstrip('/')}{endpoint}"
76
+
77
+ # Chuyển tiếp cả header xác thực đến worker thợ
78
+ headers = {"Content-Type": "application/json", "x-api-key": auth_key}
79
+
80
+ async with load_lock: worker_load[worker_url] += 1
81
+ print(f"Forwarding to {worker_url}. Current loads: {worker_load}")
82
+
83
+ try:
84
+ async with aiohttp.ClientSession() as session:
85
+ async with session.post(target_url, json=payload, headers=headers, timeout=125) as response:
86
+ response.raise_for_status()
87
+ return await response.json()
88
+ finally:
89
+ async with load_lock: worker_load[worker_url] -= 1
90
+ print(f"Request to {worker_url} finished. Current loads: {worker_load}")
91
+
92
+ # --- API Endpoint của Load Balancer ---
93
+ @app.post("/dispatch-maintenance")
94
+ async def dispatch_maintenance_endpoint(payload: APIKeyPayload, x_api_key: str = Header(...)):
95
+ """Endpoint DUY NHẤT mà Client Tool sẽ gọi."""
96
+ # 1. Xác thực request từ client
97
+ if x_api_key != API_AUTH_KEY:
98
+ raise HTTPException(status_code=401, detail="Invalid API Key for Load Balancer")
99
+
100
+ # 2. Chọn worker và chuyển tiếp request
101
+ try:
102
+ worker_to_use = await select_worker()
103
+ result = await forward_request_to_worker(worker_to_use, payload.dict(), API_AUTH_KEY)
104
+ return result
105
+ except ValueError as e:
106
+ raise HTTPException(status_code=503, detail=str(e))
107
+ except aiohttp.ClientResponseError as e:
108
+ raise HTTPException(status_code=e.status, detail=f"Worker thợ báo lỗi: {e.message}")
109
+ except Exception as e:
110
+ raise HTTPException(status_code=504, detail=f"Lỗi kết nối đến worker thợ: {str(e)}")
111
+
112
+ @app.get("/")
113
+ def read_root():
114
+ return {"message": "Load Balancer is running."}
115
+
116
+ #<--KẾT THÚC TOÀN BỘ CODE CHO FILE load_balancer.py -->