لا تحتاج كل عملية أتمتة إلى بنية متعددة المناطق. فالجدوى الحقيقية تظهر في ثلاث حالات فقط:
- أن تكون مواقعك المستهدفة موزّعة على أكثر من قارة.
- أن يفرض عليك اتفاق مستوى الخدمة استمرارية شبه كاملة.
- أن يُلزمك الامتثال بإبقاء جزء من المعالجة داخل حدود جغرافية محددة.
خارج هذه الحالات، غالبًا ما يضيف التوزيع الإقليمي عبئًا تشغيليًا يفوق قيمته.
حين تنطبق إحدى هذه الحالات، يصبح توزيع عمال حل CAPTCHA قرب المواقع المستهدفة قرارًا هندسيًا مدروسًا: فهو يقصّر مسار البروكسي إلى الهدف، ويمنحك تكرارًا احتياطيًا يمتص انقطاع أي منطقة، ويحافظ على ثبات الأداء عبر الأسواق. تخيّل فريقًا في الخليج يجمع بيانات من متاجر أوروبية وآسيوية في آن واحد: عامل واحد في منطقة أمريكية سيضيف مئات الميلي ثانية لكل طلب بعيد. الأسطر التالية توضّح كيف تبني هذا النمط فوق CaptchaAI دون تعقيد لا لزوم له.
متى تستحق البنية متعددة المناطق العناء؟
قبل كتابة سطر واحد من Terraform، أجب عن أربعة أسئلة. إن مالت أغلب إجاباتك إلى العمود الأيمن فالتوزيع الإقليمي يخدمك فعلًا؛ وإن مالت إلى العمود الأيسر فابدأ بمنطقة واحدة وراقب قبل أن تتوسّع.
| السؤال | إذا كانت الإجابة نعم | إذا كانت الإجابة لا |
|---|---|---|
| هل تستهدف مواقع أو مستخدمين في أكثر من قارة؟ | التوزيع الإقليمي منطقي | قد تكفي منطقة واحدة |
| هل لديك متطلبات uptime أو failover صارمة؟ | التعدد الإقليمي مفيد | أبقِ التصميم أبسط |
| هل البيانات أو الامتثال يفرضان بقاء بعض الحمل محليًا؟ | استخدم مناطق منفصلة بوضوح | لا حاجة لهذا التعقيد غالبًا |
| هل حجم المهام ما زال منخفضًا نسبيًا؟ | ابدأ بمنطقة واحدة وراقب | لا تتعجل في التوسع |
الجدول التالي يترجم هذا القرار إلى مواقف تشغيلية ملموسة، ويقارن ما تقدّمه منطقة واحدة مقابل توزيع متعدد المناطق:
| الوضع | منطقة واحدة | متعدد المناطق |
|---|---|---|
| استهداف مواقع داخل بلد واحد | كافية | مبالغة |
| مواقع مستهدفة عالمية | زمن وصول إضافي 100-300 مللي ثانية | زمن وصول محلي لكل منطقة |
| متطلب توافر عالٍ (وقت تشغيل شبه كامل) | يصعب ضمانه | تكرار احتياطي طبيعي |
| إقامة البيانات التنظيمية | يتعذّر الامتثال | معالجة محلية |
| <1000 مهمة/الساعة | كافية | تعقيد بلا داعٍ |
| >10000 مهمة/الساعة | حدود التوسع | توزيع للحمل |
كيف تبدو البنية على أرض الواقع
[Task Router]
(Route53 / Load Balancer)
↙ ↓ ↘
[US-East] [EU-West] [AP-Southeast]
Workers Workers Workers
↓ ↓ ↓
[CaptchaAI API] ← shared API key
↓ ↓ ↓
[Central DB / Queue]
(Results aggregation)
- عمّال إقليميون: كل منطقة تدير أسطولها الخاص وطابور مهامها المحلي، منفصلة عن غيرها.
- مفتاح CaptchaAI API مشترك: تستخدمه جميع المناطق دون الحاجة إلى مفاتيح منفصلة.
- مخزن مركزي: تتجمّع فيه النتائج من كل المناطق للتحليل والمقارنة.
الفصل الكامل بين المناطق هو ما يجعل سقوط إحداها لا يوقف الباقي.
نشر العمال حسب المنطقة
عامل Python واعٍ بالمنطقة
يرسل العامل التالي المهمة إلى CaptchaAI عبر in.php، ثم يستطلع res.php دوريًا حتى تجهز النتيجة. المهم هنا أنه يُرفق بكل نتيجة وسم المنطقة وزمن الحل — وهي بيانات ستحتاجها لاحقًا في المراقبة والمقارنة بين المناطق:
import os
import time
import requests
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
REGION = os.environ.get("WORKER_REGION", "us-east-1")
RESULT_QUEUE_URL = os.environ["RESULT_QUEUE_URL"]
def solve_captcha(task):
"""Solve CAPTCHA and tag with region metadata."""
start = time.time()
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": task["method"],
"googlekey": task["sitekey"],
"pageurl": task["pageurl"],
"json": 1
})
data = resp.json()
if data.get("status") != 1:
return {
"task_id": task["task_id"],
"error": data.get("request"),
"region": REGION
}
captcha_id = data["request"]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": captcha_id, "json": 1
}).json()
if result.get("status") == 1:
return {
"task_id": task["task_id"],
"solution": result["request"],
"region": REGION,
"duration": time.time() - start,
"api_latency_ms": round((time.time() - start) * 1000)
}
if result.get("request") != "CAPCHA_NOT_READY":
return {
"task_id": task["task_id"],
"error": result.get("request"),
"region": REGION
}
return {"task_id": task["task_id"], "error": "TIMEOUT", "region": REGION}
موجّه المهام حسب النطاق
يوجّه الموجّه كل مهمة إلى الطابور الأقرب جغرافيًا اعتمادًا على امتداد نطاق الموقع المستهدف (TLD). النطاقات غير المعروفة تذهب إلى المنطقة الافتراضية دون أن تتعطّل المعالجة:
from urllib.parse import urlparse
# Region mapping by target site TLD/domain
REGION_MAP = {
".co.uk": "eu-west-1",
".de": "eu-central-1",
".fr": "eu-west-3",
".jp": "ap-northeast-1",
".com.au": "ap-southeast-2",
".com": "us-east-1", # Default
}
REGION_QUEUES = {
"us-east-1": "sqs://captcha-tasks-us-east",
"eu-west-1": "sqs://captcha-tasks-eu-west",
"ap-southeast-1": "sqs://captcha-tasks-ap-southeast",
}
def route_task(task):
"""Route task to the closest regional queue."""
domain = urlparse(task["pageurl"]).netloc
target_region = "us-east-1" # Default
for suffix, region in REGION_MAP.items():
if domain.endswith(suffix):
target_region = region
break
queue = REGION_QUEUES.get(target_region, REGION_QUEUES["us-east-1"])
send_to_queue(queue, task)
return target_region
تجهيز البنية التحتية
هيكل Terraform الأساسي
يعرّف هذا الهيكل قائمة المناطق مرة واحدة، ثم ينشر أسطول عمال وطابور SQS لكل منطقة عبر for_each، مع طابور نتائج مركزي واحد يجمع مخرجات الجميع:
# Define regions
variable "regions" {
default = ["us-east-1", "eu-west-1", "ap-southeast-1"]
}
# Deploy worker fleet per region
module "captcha_workers" {
for_each = toset(var.regions)
source = "./modules/captcha-worker"
region = each.key
worker_count = var.workers_per_region
api_key_secret_arn = aws_secretsmanager_secret.captchaai_key.arn
task_queue_arn = aws_sqs_queue.tasks[each.key].arn
result_queue_arn = aws_sqs_queue.results.arn
}
# SQS queue per region for task intake
resource "aws_sqs_queue" "tasks" {
for_each = toset(var.regions)
name = "captcha-tasks-${each.key}"
}
# Central result queue
resource "aws_sqs_queue" "results" {
name = "captcha-results-central"
}
محاكاة محلية عبر Docker Compose
قبل الدفع إلى السحابة، حاكِ التوزيع على جهازك: ثلاث خدمات عمال بمناطق مختلفة تتشارك خادم Redis واحدًا كوسيط طوابير. هذه الطريقة تكشف أخطاء التوجيه مبكرًا دون تكلفة سحابية:
version: "3.8"
services:
worker-us:
build: ./worker
environment:
- CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
- WORKER_REGION=us-east-1
- TASK_QUEUE=redis://redis:6379/0
depends_on:
- redis
worker-eu:
build: ./worker
environment:
- CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
- WORKER_REGION=eu-west-1
- TASK_QUEUE=redis://redis:6379/1
worker-ap:
build: ./worker
environment:
- CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
- WORKER_REGION=ap-southeast-1
- TASK_QUEUE=redis://redis:6379/2
redis:
image: redis:7-alpine
مراقبة صحة كل منطقة
لا تكتمل البنية الموزّعة دون رؤية لحظية لحالة كل منطقة. يفحص السكربت التالي نقطة الصحة في كل منطقة كل دقيقة، ويجمع زمن الوصول وعدد العمال النشطين وعمق الطابور في جدول واحد:
JavaScript
const axios = require("axios");
const REGIONS = ["us-east-1", "eu-west-1", "ap-southeast-1"];
async function checkRegionHealth() {
const health = {};
for (const region of REGIONS) {
const endpoint = `https://${region}.workers.example.com/health`;
try {
const start = Date.now();
const resp = await axios.get(endpoint, { timeout: 5000 });
health[region] = {
status: "healthy",
latencyMs: Date.now() - start,
activeWorkers: resp.data.activeWorkers,
queueDepth: resp.data.queueDepth,
};
} catch (err) {
health[region] = { status: "unhealthy", error: err.message };
}
}
return health;
}
// Periodic health check
setInterval(async () => {
const health = await checkRegionHealth();
console.table(health);
}, 60000);
التحويل التلقائي عند الأعطال
حين تسقط منطقة، يجب إعادة توزيع مهامها فورًا بدل تركها تتراكم. يعمل المنطق التالي على ثلاث خطوات:
- حصر المناطق الصحية المتاحة حاليًا.
- اختيار أقلها ازدحامًا بديلًا لكل منطقة متعطّلة.
- إيقاف التوجيه بالكامل إذا تعطّلت كل المناطق بدل إرسال الحمل إلى فراغ.
def failover_check(region_health):
"""Redirect tasks from unhealthy regions."""
healthy_regions = [
r for r, h in region_health.items()
if h["status"] == "healthy"
]
if not healthy_regions:
raise RuntimeError("All regions unhealthy")
redirects = {}
for region, health in region_health.items():
if health["status"] == "unhealthy":
# Pick the healthy region with lowest queue depth
target = min(
healthy_regions,
key=lambda r: region_health[r].get("queue_depth", 0)
)
redirects[region] = target
print(f"Failover: {region} → {target}")
return redirects
ماذا يكلّفك التوزيع متعدد المناطق؟
الكلفة الإضافية للتوزيع الإقليمي تأتي من البنية التحتية وحدها، لا من CaptchaAI:
| مكون | عامل التكلفة | التحسين |
|---|---|---|
| حالات العمال | حساب لكل منطقة | مقياس تلقائي إلى 0 عندما يكون خاملاً |
| نقل البيانات عبر المناطق | 0.02$/GB بين المناطق | تقليل حجم الحمولة الناتجة |
| طوابير SQS | التسعير حسب الطلب | رسائل دفعة حيثما أمكن ذلك |
| واجهة برمجة تطبيقات CaptchaAI | نفس التكلفة بغض النظر عن المنطقة | لا يوجد قسط متعدد المناطق |
خلاصة التكلفة من زاوية CaptchaAI:
- المحاسبة على عدد الـ Threads المتزامنة لا على كل عملية حل، مع عدد غير محدود من عمليات الحل لكل Thread.
- السعر نفسه بصرف النظر عن موقع العامل، دون أي زيادة مقابل تشغيل عدة مناطق.
- العبء الإضافي الوحيد هو حساب العمال ونقل البيانات بين المناطق.
حل المشكلات الشائعة
معظم أعطال البنية الموزّعة ترجع إلى منطق التوجيه أو إلى الخلط بين صحة المنطقة وعمق طابورها:
| المشكلة | السبب | الإجراء |
|---|---|---|
| المهام تتجه باستمرار إلى منطقة واحدة | منطق التوجيه لا يغطي النطاقات أو suffixes بشكل كافٍ | راجع REGION_MAP وسجّل قرارات التوجيه فعليًا |
| التحول الاحتياطي ينقل الحمل إلى منطقة مزدحمة | failover يعتمد على الصحة فقط لا على عمق الطابور | اجمع بين health وqueue depth قبل إعادة التوجيه |
| النتائج تتأخر رغم قرب المنطقة من الهدف | الاختناق في الطابور المركزي أو النشر النهائي لا في العامل الإقليمي | راقب طبقة التجميع المركزية بدل لوم المنطقة فقط |
| إدارة الأسرار أصبحت معقدة | مفتاح واحد ومخازن متعددة من دون سياسة موحدة | استخدم مدير أسرار مركزيًا مع توزيع مضبوط لكل منطقة |
أسئلة شائعة
هل يرفع التوزيع متعدد المناطق معدل الحل نفسه؟
لا. معدل حل CAPTCHA يعتمد على نوع الاختبار وعلى خوادم CaptchaAI، لا على موقع عاملك. ما يمنحك إياه التوزيع الإقليمي هو زمن وصول أقل بين العامل وموقعه المستهدف، وتكرار احتياطي يحافظ على استمرارية العمل عند انقطاع منطقة — وكلاهما يحسّن ثبات الأداء العام لا نسبة النجاح لكل مهمة.
متى أضيف منطقة ثانية بدل الاكتفاء بواحدة؟
ابدأ بمنطقة واحدة قرب أكبر تجمّع لمواقعك المستهدفة، وراقب زمن الوصول وعمق الطوابير. أضف الثانية حين يصبح جزء ملموس من أهدافك في قارة أخرى، أو حين يفرض اتفاق مستوى الخدمة تكرارًا احتياطيًا لا تضمنه منطقة واحدة.
كيف يرتبط البروكسي بموقع العامل؟
الفائدة الحقيقية للتوزيع الإقليمي تظهر عند اقتران العامل ببروكسي قريب من الموقع المستهدف، إذ يقصُر المسار الشبكي بينهما. وزّع عمالك قرب مواقعك المستهدفة، لا قرب خوادم CaptchaAI؛ فالأخيرة تخدم الطلبات عالميًا بصرف النظر عن مكان العامل.
كيف أتأكد أن التوزيع الإقليمي خفّض زمن الوصول فعلًا؟
قِس ولا تفترض. يرفق العامل حقلي duration وapi_latency_ms بوسم المنطقة لكل نتيجة؛ اجمعها في مخزنك المركزي وقارن وسيط زمن الوصول لكل منطقة قبل التوزيع وبعده. إن لم ينخفض للأهداف القريبة، فالخلل غالبًا في البروكسي أو منطق التوجيه لا في المنطقة نفسها.
الخطوات التالية
- ابدأ سريعًا مع CaptchaAI وحلّ أول كابتشا في خمس دقائق
- حلّ reCAPTCHA v2 عبر الـ API خطوة بخطوة
- التعامل مع Cloudflare Turnstile عبر الـ API
- حلّ GeeTest v3 عبر الـ API