DevOps và Mở Rộng

Kiến trúc giải CAPTCHA đa vùng với CaptchaAI

Triển khai một khu vực có nghĩa là một điểm lỗi duy nhất và tăng thêm độ trễ cho các mục tiêu ở xa. Kiến trúc đa khu vực triển khai công cụ CAPTCHA gần các trang web mục tiêu, giảm thời gian truy cập khứ hồi API và khắc phục tình trạng ngừng hoạt động trong khu vực.

Tổng quan về kiến trúc

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

Mỗi khu vực điều hành công nhân độc lập. Tất cả đều chia sẻ cùng một khóa API CaptchaAI và đẩy kết quả đến cửa hàng trung tâm.

Khi vấn đề đa khu vực

Tình huống Vùng đơn Đa vùng
Trang web mục tiêu ở một quốc gia Đủ Quá mức cần thiết
Trang web mục tiêu toàn cầu Độ trễ được thêm vào 100–300 ms Độ trễ cục bộ trên mỗi khu vực
Yêu cầu thời gian hoạt động 99,9% Khó đảm bảo Sự dư thừa tự nhiên
Nơi lưu trữ dữ liệu theo quy định Không thể tuân thủ Xử lý cục bộ
< 1.000 nhiệm vụ/hour Tốt thôi Sự phức tạp không cần thiết
> 10.000 nhiệm vụ/hour Giới hạn tỷ lệ Phân phối tải

Triển khai công nhân khu vực

Python Worker (Nhận biết khu vực)

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}

Bộ định tuyến tác vụ

Định tuyến các nhiệm vụ đến khu vực gần địa điểm mục tiêu nhất:

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

Thiết lập cơ sở hạ tầng

Bộ xương địa hình

# 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 (Mô phỏng đa vùng cục bộ)

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

Theo dõi sức khỏe mỗi khu vực

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

Chiến lược chuyển đổi dự phòng

Khi một khu vực ngừng hoạt động, hãy phân phối lại nhiệm vụ của khu vực đó:

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

Cân nhắc chi phí

thành phần Yếu tố chi phí Tối ưu hóa
Trường hợp công nhân Tính toán theo vùng Tự động chia tỷ lệ về 0 khi không hoạt động
Truyền dữ liệu xuyên khu vực 0,02/GB giữa các khu vực Giảm thiểu kích thước tải trọng kết quả
Hàng đợi SQS Định giá theo yêu cầu Gửi tin nhắn hàng loạt nếu có thể
API CaptchaAI Chi phí như nhau bất kể khu vực Không có phí bảo hiểm đa vùng

CaptchaAI tính mức giá như nhau bất kể vị trí của người lao động – chi phí đa khu vực chỉ là cơ sở hạ tầng.

Chính sách chuyển đổi dự phòng

  • Dừng định tuyến các tác vụ mới vào khu vực bị xuống cấp khi độ trễ, tỷ lệ lỗi hoặc tình trạng proxy vượt quá ngưỡng chính sách.
  • Cố tình làm cạn kiệt công việc trên chuyến bay thay vì chuyển đổi đột ngột mọi hàng đợi và phiên.
  • Chỉ tiếp tục lưu lượng truy cập sau khi khu vực đáp ứng các cổng tình trạng tương tự được sử dụng trước khi chuyển đổi dự phòng.

Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
Một khu vực luôn chậm hơn Khoảng cách từ máy chủ CaptchaAI So sánh độ trễ cơ bản; có thể được mong đợi
Định tuyến tác vụ sẽ gửi mọi thứ đến một khu vực Định tuyến dựa trên tên miền quá rộng Thêm các quy tắc định tuyến chi tiết hơn
Chuyển đổi dự phòng không kích hoạt Điểm cuối kiểm tra tình trạng không phản hồi Đảm bảo điểm cuối sức khỏe nằm trên một đường dẫn riêng biệt với logic của nhân viên
Số dư khóa API cạn kiệt nhanh hơn Tất cả các khu vực chia sẻ một khóa Dự kiến – giám sát việc sử dụng tổng hợp

Câu hỏi thường gặp

Tôi có cần các khóa API CaptchaAI riêng biệt cho mỗi vùng không?

Không. Một khóa API hoạt động trên toàn cầu. Sử dụng một khóa duy nhất và theo dõi mức sử dụng theo từng khu vực thông qua số liệu của riêng bạn.

Số khu vực tối thiểu để có tính sẵn sàng cao là bao nhiêu?

Hai khu vực ở các khu vực địa lý khác nhau (ví dụ: US + EU) cung cấp HA cơ bản. Ba khu vực (Mỹ + EU + Châu Á) bao gồm tính sẵn có trên toàn cầu.

Tôi có nên triển khai nhân viên trong cùng khu vực với máy chủ của CaptchaAI không?

Cơ sở hạ tầng của CaptchaAI xử lý các yêu cầu toàn cầu. Triển khai nhân viên gần trang web mục tiêu của bạn để tối ưu hóa proxy, không phải gần CaptchaAI.

bài viết liên quan

Các bước tiếp theo

Triển khai nhân viên CaptchaAI trên nhiều khu vực —lấy khóa API của bạnvà xây dựng cơ sở hạ tầng giải CAPTCHA toàn cầu.

Hướng dẫn liên quan:

Os comentários estão desativados para este artigo.