DevOps & Scaling

Xây dựng giải quyết CAPTCHA theo sự kiện bằng AWS SNS và CaptchaAI

Việc thăm dò các kết quả CAPTCHA liên kết các luồng và tạo ra sự liên kết chặt chẽ giữa bộ sao chép của bạn và quy trình giải quyết. AWS SNS (Dịch vụ thông báo đơn giản) giải quyết những mối lo ngại này — CaptchaAI gửi kết quả tới cuộc gọi lại của bạn, cuộc gọi lại sẽ xuất bản lên SNS và bất kỳ số lượng người tiêu dùng tiếp theo nào sẽ phản ứng độc lập.

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

[Scraper] → Submit CAPTCHA → [CaptchaAI API]
                                    ↓
                            Solve completes
                                    ↓
                            Callback → [API Gateway + Lambda]
                                    ↓
                            Publish → [SNS Topic]
                                    ↓
                    ┌───────────────┼───────────────┐
                    ↓               ↓               ↓
            [SQS Queue]      [Lambda Logger]   [Email Alert]
            (result store)   (audit trail)     (on failure)

SNS cung cấp phân xuất: một kết quả CAPTCHA sẽ kích hoạt nhiều người tiêu dùng mà trình xử lý gọi lại không biết về họ.

Bước 1: Tạo chủ đề SNS

AWS CLI

aws sns create-topic --name captcha-results --output text
# Returns: arn:aws:sns:us-east-1:123456789:captcha-results

Python (boto3)

import boto3

sns = boto3.client("sns", region_name="us-east-1")

response = sns.create_topic(Name="captcha-results")
topic_arn = response["TopicArn"]
print(f"Topic ARN: {topic_arn}")

Bước 2: Xây dựng bộ thu gọi lại

Hàm Lambda này nhận kết quả gọi lại CaptchaAI và xuất bản chúng lên SNS.

Python (Trình xử lý Lambda)

import json
import os
import boto3

sns = boto3.client("sns")
TOPIC_ARN = os.environ["SNS_TOPIC_ARN"]

def lambda_handler(event, context):
    """Receive CaptchaAI callback and publish to SNS."""
    # Parse query parameters from API Gateway
    params = event.get("queryStringParameters", {}) or {}
    task_id = params.get("id", "")
    solution = params.get("code", "")

    if not task_id or not solution:
        return {"statusCode": 400, "body": "Missing id or code"}

    # Publish to SNS
    message = {
        "task_id": task_id,
        "solution": solution,
        "status": "solved"
    }

    sns.publish(
        TopicArn=TOPIC_ARN,
        Message=json.dumps(message),
        Subject="captcha-solved",
        MessageAttributes={
            "task_id": {
                "DataType": "String",
                "StringValue": task_id
            }
        }
    )

    return {"statusCode": 200, "body": "OK"}

JavaScript (Trình xử lý Lambda)

const { SNSClient, PublishCommand } = require("@aws-sdk/client-sns");

const sns = new SNSClient({ region: "us-east-1" });
const TOPIC_ARN = process.env.SNS_TOPIC_ARN;

exports.handler = async (event) => {
  const params = event.queryStringParameters || {};
  const taskId = params.id;
  const solution = params.code;

  if (!taskId || !solution) {
    return { statusCode: 400, body: "Missing id or code" };
  }

  const message = {
    task_id: taskId,
    solution: solution,
    status: "solved",
  };

  await sns.send(
    new PublishCommand({
      TopicArn: TOPIC_ARN,
      Message: JSON.stringify(message),
      Subject: "captcha-solved",
      MessageAttributes: {
        task_id: { DataType: "String", StringValue: taskId },
      },
    })
  );

  return { statusCode: 200, body: "OK" };
};

Bước 3: Gửi CAPTCHA kèm theo URL gọi lại

Trỏ pingback của CaptchaAI vào điểm cuối Cổng API của bạn:

Python

import os
import requests

API_KEY = os.environ["CAPTCHAAI_API_KEY"]
CALLBACK_URL = os.environ["CALLBACK_GATEWAY_URL"]  # API Gateway URL

def submit_captcha(sitekey, pageurl):
    """Submit CAPTCHA with SNS-backed callback."""
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "pingback": CALLBACK_URL,
        "json": 1
    })
    data = resp.json()

    if data.get("status") == 1:
        return data["request"]  # task_id
    raise RuntimeError(f"Submit failed: {data.get('request')}")

Bước 4: Đăng ký người tiêu dùng

Hàng đợi SQS (Lưu trữ kết quả)

# Subscribe an SQS queue to receive all results
sqs_arn = "arn:aws:sqs:us-east-1:123456789:captcha-results-queue"

sns.subscribe(
    TopicArn=topic_arn,
    Protocol="sqs",
    Endpoint=sqs_arn
)

Lambda (Trình ghi nhật ký kiểm tra)

# Subscribe a Lambda for audit logging
lambda_arn = "arn:aws:lambda:us-east-1:123456789:function:captcha-audit-logger"

sns.subscribe(
    TopicArn=topic_arn,
    Protocol="lambda",
    Endpoint=lambda_arn
)

Email (Cảnh báo lỗi)

# Subscribe email for error notifications with filter
sns.subscribe(
    TopicArn=topic_arn,
    Protocol="email",
    Endpoint="ops@example.com"
)

Bước 5: Sử dụng kết quả từ SQS

Công cụ quét của bạn đọc các giải pháp từ SQS thay vì thăm dò CaptchaAI:

Python

import json
import boto3

sqs = boto3.client("sqs", region_name="us-east-1")
QUEUE_URL = os.environ["SQS_QUEUE_URL"]

def get_solved_captcha(timeout=30):
    """Wait for a CAPTCHA solution from the SQS queue."""
    response = sqs.receive_message(
        QueueUrl=QUEUE_URL,
        MaxNumberOfMessages=1,
        WaitTimeSeconds=min(timeout, 20)  # Long polling (max 20s)
    )

    messages = response.get("Messages", [])
    if not messages:
        return None

    msg = messages[0]
    # SNS wraps the message — unwrap it
    sns_envelope = json.loads(msg["Body"])
    result = json.loads(sns_envelope["Message"])

    # Delete message after processing
    sqs.delete_message(
        QueueUrl=QUEUE_URL,
        ReceiptHandle=msg["ReceiptHandle"]
    )

    return result

JavaScript

const {
  SQSClient,
  ReceiveMessageCommand,
  DeleteMessageCommand,
} = require("@aws-sdk/client-sqs");

const sqs = new SQSClient({ region: "us-east-1" });
const QUEUE_URL = process.env.SQS_QUEUE_URL;

async function getSolvedCaptcha(timeout = 30) {
  const response = await sqs.send(
    new ReceiveMessageCommand({
      QueueUrl: QUEUE_URL,
      MaxNumberOfMessages: 1,
      WaitTimeSeconds: Math.min(timeout, 20),
    })
  );

  const messages = response.Messages || [];
  if (messages.length === 0) return null;

  const msg = messages[0];
  const snsEnvelope = JSON.parse(msg.Body);
  const result = JSON.parse(snsEnvelope.Message);

  await sqs.send(
    new DeleteMessageCommand({
      QueueUrl: QUEUE_URL,
      ReceiptHandle: msg.ReceiptHandle,
    })
  );

  return result;
}

Lọc tin nhắn SNS

Định tuyến các kết quả khác nhau đến những người tiêu dùng khác nhau:

# Only send failures to the ops queue
sns.subscribe(
    TopicArn=topic_arn,
    Protocol="sqs",
    Endpoint=failure_queue_arn,
    Attributes={
        "FilterPolicy": json.dumps({
            "status": ["failed", "error"]
        })
    }
)

Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
Gọi lại trả về 403 Chặn xác thực API Gateway CaptchaAI Vô hiệu hóa xác thực trên tuyến gọi lại; thay vào đó hãy sử dụng xác thực dựa trên mã thông báo
Tin nhắn SQS không đến SNS †' Thiếu quyền SQS Thêm quyền sns:Publish vào chính sách hàng đợi SQS
Kết quả trùng lặp được xử lý SNS cung cấp ít nhất một lần Triển khai tính tạm thời – kiểm tra task_id trước khi xử lý
Khởi động nguội Lambda trì hoãn cuộc gọi lại Đồng thời được cung cấp chưa được đặt Bật tính năng đồng thời được cung cấp cho lệnh gọi lại Lambda

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

Tại sao nên sử dụng SNS thay vì xử lý kết quả trực tiếp trong lệnh gọi lại Lambda?

SNS tách trình xử lý gọi lại khỏi logic xuôi dòng. Bạn có thể thêm người tiêu dùng mới (ghi nhật ký, cảnh báo, phân tích) mà không cần sửa đổi lệnh gọi lại Lambda. Cuộc gọi lại vẫn đơn giản và nhanh chóng.

Độ trễ được thêm vào từ lớp SNS là bao nhiêu?

SNS tăng thêm 10–50 mili giây cho mỗi tin nhắn. Vì việc giải CAPTCHA mất 5–30 giây nên chi phí này không đáng kể.

Tôi có thể sử dụng SNS FIFO để xử lý đơn hàng không?

Vâng. Sử dụng chủ đề SNS FIFO với hàng đợi SQS FIFO nếu bạn cần kết quả được sắp xếp. Đặt MessageGroupId thành ID nhiệm vụ để sắp xếp thứ tự cho mỗi nhiệm vụ.

bài viết liên quan

Các bước tiếp theo

Xây dựng giải pháp CAPTCHA theo sự kiện —lấy khóa API CaptchaAI của bạnvà kết nối nó với quy trình sự kiện AWS của bạn.

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

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

Postagens relacionadas

DevOps & Scaling AWS Lambda + CaptchaAI: Giải mã CAPTCHA không cần máy chủ
Hướng dẫn Dev Ops về AWS Lambda + Captcha AI: Giải mã CAPTCHA không cần máy chủ, với các quyết định về kiến ​​trúc, cân nhắc vận hành và mẫu tự động hóa cho quy...

Hướng dẫn Dev Ops về AWS Lambda + Captcha AI: Giải mã CAPTCHA không cần máy chủ, với các quyết định về kiến ​​...

Apr 25, 2026
DevOps & Scaling Công nhân giải quyết CAPTCHA tự động mở rộng quy mô
Hướng dẫn Dev Ops về Công nhân giải quyết quy trình tự động mở rộng CAPTCHA, với các quyết định về kiến ​​trúc, các cân nhắc vận hành và mô hình tự động hóa cho...

Hướng dẫn Dev Ops về Công nhân giải quyết quy trình tự động mở rộng CAPTCHA, với các quyết định về kiến ​​trúc...

Apr 24, 2026
Tutorials Xây dựng hàng đợi giải CAPTCHA bằng Python với CaptchaAI
Hướng dẫn từng bước để Xây dựng hàng đợi giải mã CAPTCHA bằng Python với Captcha AI, với các ví dụ có thể sử dụng lại trực tiếp và quy trình làm việc Captcha AI...

Hướng dẫn từng bước để Xây dựng hàng đợi giải mã CAPTCHA bằng Python với Captcha AI, với các ví dụ có thể sử d...

May 01, 2026