DevOps & Mise à l'Échelle

Architecture de résolution de CAPTCHA multirégion avec CaptchaAI

Le déploiement dans une seule région signifie un point de défaillance unique et une latence supplémentaire pour les cibles distantes. L'architecture multirégionale déploie des agents CAPTCHA à proximité des sites cibles, réduit le temps d'aller-retour des API et survit aux pannes régionales.

Quand faut-il vraiment passer au multi-région ?

Signal Le multi-région vaut souvent l'effort Une seule région reste souvent suffisante
Répartition des cibles Le trafic vise plusieurs zones géographiques distinctes La majorité des cibles restent concentrées dans une même zone
Tolérance à la panne Un incident régional doit rester invisible pour les clients internes Une courte interruption est acceptable
Contraintes de conformité Certaines données ou sessions doivent rester dans une région donnée Aucune contrainte de résidence ne vous impose un traitement local
Volumétrie Les pics sont assez élevés pour justifier du routage et de l'observabilité supplémentaires Le volume reste assez faible pour qu'une seule région reste simple et stable

Présentation de l'architecture

                    [Task Router]
                    (Route53 / Load Balancer)
                    ↙        ↓        ↘
        [US-East]      [EU-West]     [AP-Southeast]
        Workers        Workers        Workers
            ↓              ↓              ↓
        [CaptchaAI API] ← shared API key
            ↓              ↓              ↓
        [Central DB / Queue]
        (Results aggregation)

Chaque région dispose de travailleurs indépendants. Tous partagent la même clé API CaptchaAI et transmettent les résultats à un magasin central.

Quand le multi-région est important

Situation Région unique Multi-région
Cibler des sites dans un pays Suffisant Exagération
Sites cibles mondiaux 100 à 300 ms de latence ajoutée Latence locale par région
Exigence de disponibilité de 99,9 % Difficile de garantir Redondance naturelle
Résidence des données réglementaires Je ne peux pas me conformer Traiter localement
< 1 000 tâches/hour Très bien Complexité inutile
> 10 000 tâches/hour Limites de mise à l'échelle Distribue la charge

Déploiement régional des travailleurs

Python Worker (sensible à la région)

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}

Routeur de tâches

Acheminez les tâches vers la région la plus proche du site cible :

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

Configuration de l'infrastructure

Squelette Terraforme

# 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 (simulation multi-régions locale)

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

Surveillance de la santé par région

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);

Stratégie de basculement

Lorsqu'une région tombe en panne, redistribuez ses tâches :

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

Considérations relatives aux coûts

Composant Facteur de coût Optimisation
Instances de travail Calcul par région Mise à l'échelle automatique à 0 en cas d'inactivité
Transfert de données entre régions 0,02 $/GB entre les régions Réduire la taille de la charge utile des résultats
Files d'attente SQS Tarification par demande Messages par lots lorsque cela est possible
API CaptchaAI Même coût quelle que soit la région Pas de prime multirégion

CaptchaAI facture les mêmes tarifs quel que soit l'emplacement du travailleur : le coût multirégional concerne uniquement l'infrastructure.

Dépannage

Problème Parce que Corriger
Une région constamment plus lente Distance des serveurs CaptchaAI Comparez la latence de base ; on peut s'attendre
Le routage des tâches envoie tout vers une seule région Routage basé sur le domaine trop large Ajouter des règles de routage plus granulaires
Le basculement ne se déclenche pas Le point de terminaison de la vérification de l'état ne répond pas Assurez-vous que le point de terminaison d’intégrité se trouve sur un chemin distinct de la logique du travailleur
Le solde des clés API s'épuise plus rapidement Toutes les régions partagent une clé Attendu : surveillez l'utilisation globale

FAQ

Ai-je besoin de clés API CaptchaAI distinctes par région ?

Non. Une clé API fonctionne à l’échelle mondiale. Utilisez une clé unique et suivez l'utilisation par région grâce à vos propres métriques.

Quel est le nombre minimum de régions pour la haute disponibilité ?

Deux régions situées dans des zones géographiques différentes (par exemple, États-Unis + UE) fournissent une HA de base. Trois régions (États-Unis + UE + Asie) couvrent la disponibilité mondiale.

Dois-je déployer des Workers dans la même région que les serveurs de CaptchaAI ?

L'infrastructure de CaptchaAI gère les demandes globales. Déployez des travailleurs à proximité de vos sites cibles pour l'optimisation du proxy, pas à proximité de CaptchaAI.

Articles connexes

Prochaines étapes

Déployez les travailleurs CaptchaAI dans plusieurs régions –récupérez votre clé APIet construire une infrastructure mondiale de résolution de CAPTCHA.

Guides associés :

Les commentaires sont désactivés pour cet article.