Kazıma altyapınız binlerce CAPTCHA çözüm isteği gönderdiğinde, tek bir çalışan süreç darboğazına uğrar. Yük dengeleyici, istekleri birden fazla çalışana dağıtarak verimi artırır, yük devretmeyi etkinleştirir ve yatay olarak ölçeklendirmenize olanak tanır.
Mimariye Genel Bakış
[Scraper 1] ──┐ ┌── [Worker 1] ──→ CaptchaAI API
[Scraper 2] ──┤── [Load Balancer] ──┤── [Worker 2] ──→ CaptchaAI API
[Scraper 3] ──┘ └── [Worker 3] ──→ CaptchaAI API
NGINX Yapılandırması
Round-Robin (Varsayılan)
upstream captcha_workers {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
}
server {
listen 80;
server_name captcha.internal;
location /solve {
proxy_pass http://captcha_workers;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 10s;
proxy_read_timeout 300s; # CAPTCHA solving can take minutes
}
location /health {
proxy_pass http://captcha_workers;
proxy_connect_timeout 5s;
proxy_read_timeout 5s;
}
}
En Az Bağlantı (CAPTCHA Çözümü İçin Daha İyi)
upstream captcha_workers {
least_conn; # Route to worker with fewest active connections
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080 weight=2; # Higher capacity worker
# Health checks
server 10.0.1.10:8080 max_fails=3 fail_timeout=30s;
server 10.0.1.11:8080 max_fails=3 fail_timeout=30s;
server 10.0.1.12:8080 max_fails=3 fail_timeout=30s;
}
Yedekleme Çalışanlarıyla
upstream captcha_workers {
least_conn;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080 backup; # Only used when others are down
}
Çalışan API Sunucusu
Python (Şişe)
import os
import time
import threading
import requests
from flask import Flask, request, jsonify
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
app = Flask(__name__)
# Track active tasks for load reporting
active_tasks = 0
tasks_lock = threading.Lock()
max_concurrent = int(os.environ.get("MAX_CONCURRENT", "20"))
@app.route("/solve", methods=["POST"])
def solve():
global active_tasks
with tasks_lock:
if active_tasks >= max_concurrent:
return jsonify({"error": "WORKER_AT_CAPACITY"}), 503
active_tasks += 1
try:
data = request.json
result = solve_captcha(data)
return jsonify(result)
finally:
with tasks_lock:
active_tasks -= 1
@app.route("/health")
def health():
with tasks_lock:
load = active_tasks / max_concurrent
return jsonify({
"status": "healthy" if load < 0.9 else "overloaded",
"active_tasks": active_tasks,
"max_concurrent": max_concurrent,
"load_pct": round(load * 100, 1)
}), 200 if load < 0.9 else 503
def solve_captcha(data):
session = requests.Session()
payload = {
"key": API_KEY,
"method": data.get("method", "userrecaptcha"),
"googlekey": data.get("sitekey"),
"pageurl": data.get("pageurl"),
"json": 1
}
if data.get("proxy"):
payload["proxy"] = data["proxy"]
payload["proxytype"] = data.get("proxytype", "HTTP")
resp = session.post("https://ocr.captchaai.com/in.php", data=payload)
result = resp.json()
if result.get("status") != 1:
return {"error": result.get("request")}
captcha_id = result["request"]
for _ in range(60):
time.sleep(5)
poll = session.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": captcha_id, "json": 1
}).json()
if poll.get("status") == 1:
return {"solution": poll["request"], "captcha_id": captcha_id}
if poll.get("request") != "CAPCHA_NOT_READY":
return {"error": poll.get("request")}
return {"error": "TIMEOUT"}
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, threaded=True)
JavaScript (Ekspres)
const express = require("express");
const axios = require("axios");
const API_KEY = process.env.CAPTCHAAI_API_KEY;
const MAX_CONCURRENT = parseInt(process.env.MAX_CONCURRENT || "20", 10);
const PORT = parseInt(process.env.PORT || "8080", 10);
let activeTasks = 0;
const app = express();
app.use(express.json());
app.post("/solve", async (req, res) => {
if (activeTasks >= MAX_CONCURRENT) {
return res.status(503).json({ error: "WORKER_AT_CAPACITY" });
}
activeTasks++;
try {
const result = await solveCaptcha(req.body);
res.json(result);
} catch (err) {
res.status(500).json({ error: err.message });
} finally {
activeTasks--;
}
});
app.get("/health", (req, res) => {
const load = activeTasks / MAX_CONCURRENT;
const status = load < 0.9 ? "healthy" : "overloaded";
res
.status(load < 0.9 ? 200 : 503)
.json({ status, activeTasks, maxConcurrent: MAX_CONCURRENT, loadPct: Math.round(load * 100) });
});
async function solveCaptcha(data) {
const submitResp = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: {
key: API_KEY,
method: data.method || "userrecaptcha",
googlekey: data.sitekey,
pageurl: data.pageurl,
json: 1,
},
});
if (submitResp.data.status !== 1) {
return { error: submitResp.data.request };
}
const captchaId = submitResp.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const pollResp = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "get", id: captchaId, json: 1 },
});
if (pollResp.data.status === 1) {
return { solution: pollResp.data.request, captchaId };
}
if (pollResp.data.request !== "CAPCHA_NOT_READY") {
return { error: pollResp.data.request };
}
}
return { error: "TIMEOUT" };
}
app.listen(PORT, () => console.log(`Worker listening on port ${PORT}`));
Yönlendirme Stratejilerinin Karşılaştırılması
| Strateji | Nasıl Çalışır? | En İyisi |
|---|---|---|
| Round-Robin | Sıralı dönüş | Eşit kapasitede çalışanlar |
| En Az Bağlantı | En az yüklenene rota | CAPTCHA çözme (değişken görev süresi) |
| Ağırlıklı | Ağırlıkla orantılı | Karma kapasiteli çalışanlar |
| IP Karması | Aynı müşteri – aynı çalışan | Oturum benzeşimi gerekli |
| Rastgele | Rastgele seçim | Basit, eşit dağıtılmış yük |
Öneri: CAPTCHA çözümü için en az bağlantıyı kullanın. Görev süreleri değişiklik gösterir (5 saniye ila 120 saniye), bu nedenle sıralı döngü eşit olmayan yük oluşturur.
İstemci Tarafı Yük Dengeleme
Harici bir yük dengeleyici kullanamadığınızda istemcide yönlendirme uygulayın:
import random
import requests
class ClientLoadBalancer:
def __init__(self, workers):
self.workers = [
{"url": url, "healthy": True, "active": 0}
for url in workers
]
def get_worker(self):
healthy = [w for w in self.workers if w["healthy"]]
if not healthy:
raise Exception("No healthy workers")
return min(healthy, key=lambda w: w["active"])
def solve(self, task):
worker = self.get_worker()
worker["active"] += 1
try:
resp = requests.post(
f"{worker['url']}/solve",
json=task,
timeout=300
)
if resp.status_code == 503:
worker["healthy"] = False
return self.solve(task) # Retry on another worker
return resp.json()
except requests.RequestException:
worker["healthy"] = False
return self.solve(task)
finally:
worker["active"] -= 1
lb = ClientLoadBalancer([
"http://10.0.1.10:8080",
"http://10.0.1.11:8080",
"http://10.0.1.12:8080"
])
result = lb.solve({"sitekey": "6Le-wvkS...", "pageurl": "https://example.com"})
Algoritma seçim matrisi
- Çalışanlar homojen olduğunda ve çözüm süreleri dar bir gecikme bandında kaldığında, hepsini bir kez deneme yöntemini kullanın.
- Çözüm süresi değişkenlik gösterdiğinde ve uzun süren zorluklar tek bir çalışanın omuzlarına yüklendiğinde en az bağlantıyı kullanın.
- Yedekleme yönlendirmesini ve kaynak benzeşimini yalnızca hata izolasyonu veya oturuma duyarlı hedefler için tutun.
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| 502 Kötü Ağ Geçidi | İşçi çöktü veya çalıştırılmadı | Çalışan günlüklerini kontrol edin; bağlantı noktası bağlamayı doğrula |
| Düzensiz yük dağılımı | Değişken görev süreleri ile hepsini bir kez deneme | En az bağlantıya geç |
| Sağlık kontrolü yanlış pozitif | Geçişleri kontrol edin ancak işçi kapasitesinde | Durum yanıtına yük yüzdesini dahil et |
| Bağlantı zaman aşımı | proxy_read_timeout çok kısa |
CAPTCHA çözümü için 300+'ya ayarlayın |
SSS
2-3 çalışan için yük dengeleyiciye ihtiyacım var mı?
İstemci tarafı yük dengeleme, küçük kurulumlar için iyi çalışır. 5'ten fazla çalışanınız varsa veya SSL sonlandırma ve durum kontrolleri gibi özelliklere ihtiyacınız varsa, özel bir yük dengeleyici (NGINX, HAProxy) kullanın.
Yapışkan oturumları kullanmalı mıyım?
Hayır. CAPTCHA çözüm istekleri durum bilgisizdir; herhangi bir çalışan herhangi bir görevi yerine getirebilir. Yapışkan oturumlar, eşit olmayan yük dağılımına neden olur.
Farklı bölgelerdeki işçilerle nasıl ilgilenirim?
En yakın sağlıklı bölgeye yönlendirme yapan küresel bir yük dengeleyici (AWS Global Accelerator, Cloudflare Load Balancing) kullanın. Her bölge, o bölgedeki işçiler için kendi yerel yük dengeleyicisini çalıştırır.
İlgili Makaleler
- Captchaai Geri Arama Hatası İşleme Modelleri
- Nodejs Puppeteer Captchaai Gelişmiş Desenler
- Captcha Çözme Mimarisi Desenleri Yüksek Hacim
Sonraki Adımlar
CAPTCHA çözme veriminizi ölçeklendirin —CaptchaAI API anahtarınızı alınve bir yük dengeleyicinin arkasına konuşlandırın.
İlgili kılavuzlar: