Xử lý 10.000 CAPTCHA mỗi giờ không phải bài toán tốc độ — CaptchaAI không cần giải nhanh hơn mức trung bình 15 giây. Vấn đề là duy trì đủ request chạy song song.
Bài viết đi thẳng vào công thức concurrency, kiến trúc hàng đợi, code Python/Node.js và bảng tham số theo ba mức rủi ro bằng CaptchaAI.
Công thức tính số request đồng thời cần thiết
Một lần giải reCAPTCHA v2 mất trung bình 15 giây. Chạy tuần tự bạn chỉ đạt 240 giải/giờ; để chạm 10.000 giải/giờ, bạn cần khoảng 42 request đồng thời.
| Cách chạy | Request đồng thời | Thông lượng |
|---|---|---|
| Tuần tự | 1 | 240 giải/giờ |
| Song song | ~42 | 10.000 giải/giờ |
Điểm mấu chốt: chồng đủ request lên nhau, không phải chờ CaptchaAI trả kết quả nhanh hơn.
Chọn mức cấu hình theo khẩu vị rủi ro
Chọn một trong ba mức cấu hình trước khi build. Mức Cân bằng dùng 50 request đồng thời — điểm khởi đầu hợp lý cho hầu hết đội automation.
| Tham số | Bảo thủ | Cân bằng | Quyết liệt |
|---|---|---|---|
| MAX_CONCURRENT | 20 | 50 | 100 |
| INITIAL_WAIT | 15 giây | 12 giây | 10 giây |
| POLL_INTERVAL | 7 giây | 5 giây | 3 giây |
| MAX_POLL_ATTEMPTS | 30 | 25 | 20 |
| Thông lượng dự kiến | ~4.800/giờ | ~10.000/giờ | ~18.000/giờ |
Bắt đầu ở mức Bảo thủ, tăng dần MAX_CONCURRENT đến khi thấy lợi nhuận giảm dần.
Kiến trúc pipeline
Một pipeline thông lượng cao gồm bốn khối tách biệt, giao tiếp qua hàng đợi thay vì gọi tuần tự:
┌──────────┐ ┌────────────┐ ┌─────────────┐ ┌──────────┐
│ Task │────▶│ Submit │────▶│ CaptchaAI │────▶│ Result │
│ Queue │ │ Workers │ │ API │ │ Store │
│ (Redis) │ │ (async) │ │ │ │ (DB) │
└──────────┘ └────────────┘ └─────────────┘ └──────────┘
│ ▲
│ ┌──────────┐ │
└───▶│ Poll │────┘
│ Workers │
└──────────┘
Thành phần:
- Task queue (Redis) — giữ task CAPTCHA đang chờ, kèm sitekey và pageurl
- Submit worker — gửi task tới API CaptchaAI đồng thời
- Poll worker — kiểm tra kết quả theo khoảng thời gian tối ưu (polling)
- Result store — lưu token ngay khi có kết quả
Ví dụ thực tế: đồng bộ catalog thương mại điện tử
Một tình huống quen thuộc với đội automation ở TP.HCM và Hà Nội: đồng bộ trang sản phẩm khi sàn thương mại điện tử đổi CAPTCHA trên form đăng nhập hoặc trang giá. Kiến trúc trên áp dụng y hệt.
Với vài nghìn SKU cần refresh trong một cửa sổ bảo trì ngắn, 10.000 CAPTCHA/giờ đủ để một team QA nhỏ xử lý xong trong một ca thay vì kéo dài qua đêm.
Code Python: pipeline async
Bản triển khai async dưới đây dùng aiohttp với connection pooling và semaphore giới hạn concurrency:
# high_throughput_solver.py
import os
import asyncio
import time
import aiohttp
API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")
BASE_URL = "https://ocr.captchaai.com"
MAX_CONCURRENT = 50 # Max simultaneous solves
POLL_INTERVAL = 5 # Seconds between polls
INITIAL_WAIT = 12 # Seconds before first poll
semaphore = asyncio.Semaphore(MAX_CONCURRENT)
stats = {"submitted": 0, "solved": 0, "failed": 0, "start": 0}
async def solve_one(session, sitekey, pageurl, task_num):
"""Submit and poll a single CAPTCHA."""
async with semaphore:
try:
# Submit
async with session.get(f"{BASE_URL}/in.php", params={
"key": API_KEY, "method": "userrecaptcha",
"googlekey": sitekey, "pageurl": pageurl, "json": "1",
}) as resp:
result = await resp.json(content_type=None)
if result.get("status") != 1:
stats["failed"] += 1
return None
stats["submitted"] += 1
task_id = result["request"]
# Wait before first poll
await asyncio.sleep(INITIAL_WAIT)
# Poll
for _ in range(25):
async with session.get(f"{BASE_URL}/res.php", params={
"key": API_KEY, "action": "get",
"id": task_id, "json": "1",
}) as resp:
poll_result = await resp.json(content_type=None)
if poll_result.get("status") == 1:
stats["solved"] += 1
return poll_result["request"]
if poll_result.get("request") != "CAPCHA_NOT_READY":
stats["failed"] += 1
return None
await asyncio.sleep(POLL_INTERVAL)
stats["failed"] += 1
return None
except Exception as e:
stats["failed"] += 1
return None
async def run_batch(tasks):
"""Process a batch of CAPTCHA tasks concurrently."""
connector = aiohttp.TCPConnector(
limit=MAX_CONCURRENT,
keepalive_timeout=60,
)
async with aiohttp.ClientSession(connector=connector) as session:
coros = [
solve_one(session, task["sitekey"], task["pageurl"], i)
for i, task in enumerate(tasks)
]
results = await asyncio.gather(*coros)
return results
async def main():
# Generate test tasks (replace with your task source)
tasks = [
{
"sitekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
"pageurl": "https://www.google.com/recaptcha/api2/demo",
}
for _ in range(100) # Start with 100 tasks
]
stats["start"] = time.time()
print(f"Processing {len(tasks)} tasks with {MAX_CONCURRENT} concurrent workers")
results = await run_batch(tasks)
elapsed = time.time() - stats["start"]
print(f"\nCompleted in {elapsed:.0f}s")
print(f"Submitted: {stats['submitted']}")
print(f"Solved: {stats['solved']}")
print(f"Failed: {stats['failed']}")
print(f"Throughput: {stats['solved'] / (elapsed / 3600):.0f} solves/hour")
asyncio.run(main())
Code Node.js: xử lý đồng thời với axios
Phiên bản Node.js dùng axios cùng HTTPS agent keep-alive và hàng đợi giới hạn concurrency thủ công:
// high_throughput_solver.js
const axios = require('axios');
const https = require('https');
const API_KEY = process.env.CAPTCHAAI_KEY || 'YOUR_API_KEY';
const BASE = 'https://ocr.captchaai.com';
const MAX_CONCURRENT = 50;
const agent = new https.Agent({ keepAlive: true, maxSockets: MAX_CONCURRENT });
const api = axios.create({ baseURL: BASE, httpsAgent: agent, timeout: 30000 });
const stats = { submitted: 0, solved: 0, failed: 0 };
async function solveOne(sitekey, pageurl) {
try {
const submit = await api.get('/in.php', {
params: { key: API_KEY, method: 'userrecaptcha', googlekey: sitekey, pageurl, json: '1' },
});
if (submit.data.status !== 1) { stats.failed++; return null; }
stats.submitted++;
await new Promise(r => setTimeout(r, 12000));
for (let i = 0; i < 25; i++) {
const poll = await api.get('/res.php', {
params: { key: API_KEY, action: 'get', id: submit.data.request, json: '1' },
});
if (poll.data.status === 1) { stats.solved++; return poll.data.request; }
if (poll.data.request !== 'CAPCHA_NOT_READY') { stats.failed++; return null; }
await new Promise(r => setTimeout(r, 5000));
}
stats.failed++;
return null;
} catch { stats.failed++; return null; }
}
async function runWithConcurrency(tasks, limit) {
const results = [];
const executing = new Set();
for (const task of tasks) {
const p = solveOne(task.sitekey, task.pageurl).then(r => {
executing.delete(p);
return r;
});
executing.add(p);
results.push(p);
if (executing.size >= limit) {
await Promise.race(executing);
}
}
return Promise.all(results);
}
(async () => {
const tasks = Array.from({ length: 100 }, () => ({
sitekey: '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
pageurl: 'https://www.google.com/recaptcha/api2/demo',
}));
const start = Date.now();
console.log(`Processing ${tasks.length} tasks, ${MAX_CONCURRENT} concurrent`);
await runWithConcurrency(tasks, MAX_CONCURRENT);
const elapsed = (Date.now() - start) / 1000;
console.log(`\nDone in ${elapsed.toFixed(0)}s`);
console.log(`Solved: ${stats.solved}, Failed: ${stats.failed}`);
console.log(`Throughput: ${(stats.solved / (elapsed / 3600)).toFixed(0)} solves/hour`);
agent.destroy();
})();
Giám sát thông lượng theo thời gian thực
Theo dõi bốn số liệu này khi chạy ở quy mô lớn:
| Số liệu | Mục tiêu / ngưỡng |
|---|---|
| Số lần giải mỗi phút | ~167/phút |
| Tỷ lệ lỗi | Dưới 5%, tăng đột biến thì giảm concurrency |
| Độ sâu hàng đợi | Phình to → tăng worker; trống liên tục → thừa worker |
| Thời gian giải P90 | Tăng dần → CaptchaAI có thể áp rate limit |
Xử lý sự cố thường gặp
| Vấn đề | Nguyên nhân | Cách xử lý |
|---|---|---|
| Thông lượng chững ở ~5.000/giờ | Concurrency chưa đủ | Tăng MAX_CONCURRENT lên 80–100 |
| Tỷ lệ lỗi > 10% | Quá tải API hoặc proxy kém ổn định | Giảm concurrency, kiểm tra tình trạng proxy |
| Bộ nhớ tăng liên tục | Task tích lũy không giới hạn | Xử lý kết quả ngay khi có, không buffer |
ERROR_NO_SLOT_AVAILABLE |
Hàng đợi CaptchaAI đầy | Backoff và thử lại sau 5 giây |
Câu hỏi thường gặp
Với 10.000 giải/giờ, nên chọn plan CaptchaAI nào?
ADVANCE ($90/tháng, 50 thread) là điểm khởi đầu hợp lý, đúng bằng mức Cân bằng ở bảng trên. Cần biên độ an toàn hơn thì chọn PREMIUM ($170/tháng, 100 thread).
Nên dùng polling hay webhook khi chạy khối lượng lớn?
Polling như trong bài đủ dùng ở quy mô này. Webhook giảm round-trip nhưng cần endpoint public ổn định.
Vì sao tỷ lệ lỗi tăng khi tăng MAX_CONCURRENT?
Thường do proxy pool yếu hoặc chạm rate limit phía CaptchaAI. Tăng concurrency từng bước 20–30%.
Có thể chạy song song trên nhiều máy chủ không?
Có. Dùng hàng đợi dùng chung (Redis, RabbitMQ) và chạy cùng worker script trên nhiều máy — mỗi worker tự lấy task độc lập.
Bước tiếp theo
Triển khai pipeline thông lượng cao của bạn — lấy API key CaptchaAI và bắt đầu ở mức Bảo thủ.
Hướng dẫn liên quan: