Hướng Dẫn Thực Hành

Connection Keep-Alive và HTTP/2 cho lệnh gọi API CAPTCHA nhanh hơn

Tái sử dụng kết nối TCP/TLS thay vì mở mới cho từng request có thể cắt gần 80% chi phí bắt tay mỗi lần giải — không cần đổi logic gọi API tới CaptchaAI, chỉ cần đổi cách bạn mở kết nối. Hướng dẫn này dùng connection keep-alive và ghép kênh HTTP/2.

Vì sao request lặp lại làm chậm mỗi lần giải

Một lần giải reCAPTCHA v2 thường cần 5–7 request HTTP: 1 request submit tới in.php và 4–6 request polling tới res.php. Nếu mỗi request mở một kết nối mới, bạn đang trả phí bắt tay cho cùng một tác vụ nhiều lần liên tiếp.

Kịch bản Số request Chi phí bắt tay ước tính
Không giữ kết nối 5–7 ~750 mili giây
Có keep-alive 5–7 ~170 mili giây

Chênh lệch khoảng 580 mili giây mỗi lần giải. Với hệ thống chạy 10.000 lần giải/ngày, con số đó cộng dồn thành khoảng 1,6 giờ độ trễ được cắt giảm.

Python: duy trì kết nối bằng requests.Session

Thư viện requests tự động bật keep-alive khi bạn dùng đối tượng Session, không cần cấu hình thêm:

# keepalive_solver.py
import os
import time
import requests

API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")

# Create a session — reuses TCP connections across requests
session = requests.Session()
session.headers.update({"Connection": "keep-alive"})

def solve_captcha(sitekey, pageurl):
    """Solve reCAPTCHA v2 using a persistent connection."""
    # Submit — uses existing connection if available
    resp = session.get("https://ocr.captchaai.com/in.php", params={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": "1",
    })
    result = resp.json()

    if result.get("status") != 1:
        raise Exception(f"Submit failed: {result.get('request')}")

    task_id = result["request"]

    # Poll — reuses the same connection
    time.sleep(15)
    for _ in range(25):
        poll = session.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": "1",
        })
        poll_result = poll.json()

        if poll_result.get("status") == 1:
            return poll_result["request"]
        if poll_result.get("request") != "CAPCHA_NOT_READY":
            raise Exception(f"Error: {poll_result.get('request')}")

        time.sleep(5)

    raise Exception("Timeout")

# Solve multiple CAPTCHAs reusing the same connection
for i in range(5):
    token = solve_captcha(
        "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
        "https://www.google.com/recaptcha/api2/demo"
    )
    print(f"Solve {i+1}: {token[:30]}...")

5 lần giải liên tiếp ở trên chỉ mở một kết nối TCP/TLS duy nhất thay vì năm.

Python: ghép kênh HTTP/2 với httpx

Chuyển sang httpx nếu muốn tận dụng HTTP/2:

# http2_solver.py
import os
import time
import httpx

API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")
BASE_URL = "https://ocr.captchaai.com"

# HTTP/2 client with connection pooling
client = httpx.Client(http2=True, timeout=30.0)

def solve_captcha(sitekey, pageurl):
    """Solve using HTTP/2 multiplexed connections."""
    resp = client.get(f"{BASE_URL}/in.php", params={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": pageurl,
        "json": "1",
    })
    result = resp.json()

    if result.get("status") != 1:
        raise Exception(f"Submit failed: {result.get('request')}")

    task_id = result["request"]
    time.sleep(15)

    for _ in range(25):
        poll = client.get(f"{BASE_URL}/res.php", params={
            "key": API_KEY, "action": "get",
            "id": task_id, "json": "1",
        })
        poll_result = poll.json()

        if poll_result.get("status") == 1:
            return poll_result["request"]
        if poll_result.get("request") != "CAPCHA_NOT_READY":
            raise Exception(f"Error: {poll_result.get('request')}")

        time.sleep(5)

    raise Exception("Timeout")

# Multiple solves over a single HTTP/2 connection
for i in range(5):
    token = solve_captcha(
        "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
        "https://www.google.com/recaptcha/api2/demo"
    )
    print(f"Solve {i+1}: {token[:30]}...")

client.close()

Với http2=True, httpx tự thương lượng h2 nếu server hỗ trợ; nếu không, nó âm thầm quay về HTTP/1.1.

JavaScript: Axios với agent keep-alive

Trên Node.js, gắn http.Agent / https.Agent tuỳ chỉnh vào instance Axios:

// keepalive_solver.js
const axios = require('axios');
const http = require('http');
const https = require('https');

const API_KEY = process.env.CAPTCHAAI_KEY || 'YOUR_API_KEY';

// Create agents with keep-alive enabled
const httpAgent = new http.Agent({ keepAlive: true, maxSockets: 10 });
const httpsAgent = new https.Agent({ keepAlive: true, maxSockets: 10 });

// Axios instance with persistent connections
const api = axios.create({
  baseURL: 'https://ocr.captchaai.com',
  httpAgent,
  httpsAgent,
  timeout: 30000,
});

async function solveCaptcha(sitekey, pageurl) {
  // Submit — reuses connection
  const submit = await api.get('/in.php', {
    params: {
      key: API_KEY, method: 'userrecaptcha',
      googlekey: sitekey, pageurl, json: '1',
    },
  });

  if (submit.data.status !== 1) throw new Error(submit.data.request);
  const taskId = submit.data.request;

  // Poll — reuses same connection
  await new Promise(r => setTimeout(r, 15000));
  for (let i = 0; i < 25; i++) {
    const poll = await api.get('/res.php', {
      params: { key: API_KEY, action: 'get', id: taskId, json: '1' },
    });

    if (poll.data.status === 1) return poll.data.request;
    if (poll.data.request !== 'CAPCHA_NOT_READY') throw new Error(poll.data.request);
    await new Promise(r => setTimeout(r, 5000));
  }
  throw new Error('Timeout');
}

(async () => {
  for (let i = 0; i < 5; i++) {
    const token = await solveCaptcha(
      '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
      'https://www.google.com/recaptcha/api2/demo'
    );
    console.log(`Solve ${i + 1}: ${token.slice(0, 30)}...`);
  }

  // Clean up agents
  httpAgent.destroy();
  httpsAgent.destroy();
})();

Khi nào nên dùng HTTP/2 thay vì HTTP/1.1 keep-alive

  • Giải tuần tự, mỗi lần một CAPTCHA: HTTP/1.1 keep-alive là đủ, tái sử dụng kết nối theo thứ tự, không cần đầu tư thêm.
  • Giải song song hàng chục luồng trở lên: HTTP/2 ghép nhiều luồng qua một kết nối duy nhất, cắt độ trễ nhiều hơn (~70% so với ~60% của HTTP/1.1).
  • HTTP/2 không cần trình duyệt hỗ trợ vì đây là lệnh gọi API thuần, không phải tải trang web.
  • HPACK nén header trên HTTP/2, giảm thêm overhead khi gửi nhiều request nhỏ liên tục trong một batch.

Tóm lại: ít luồng thì giữ keep-alive HTTP/1.1 cho đơn giản; từ vài chục luồng song song trở lên thì chuyển sang HTTP/2.

Chọn kích thước connection pool theo mức đồng thời

Kích thước pool nên khớp với số luồng bạn chạy song song: pool quá lớn lãng phí bộ nhớ, pool quá nhỏ buộc client mở kết nối mới liên tục và triệt tiêu lợi ích của keep-alive.

Số lần giải song song Kích thước pool đề xuất
1–5 5 kết nối
5–20 10 kết nối
20–50 25 kết nối
50–100 50 kết nối
100+ Dùng HTTP/2 (1 kết nối)

Ví dụ thực tế: đội QA tại TP.HCM chọn pool theo gói CaptchaAI

Một đội QA outsourcing tại TP.HCM chạy kiểm thử song song luồng đăng ký trên gói ADVANCE ($90/tháng, 50 thread) — pool 50 kết nối, hoặc HTTP/2 với 1 kết nối ghép kênh, là mức phù hợp để không luồng nào phải chờ. Khi khối lượng tăng lên mức PREMIUM ($170/tháng, 100 thread), đội này chuyển hẳn sang HTTP/2 thay vì quản lý hàng trăm kết nối TCP song song — vừa đơn giản hơn, vừa tận dụng đúng số thread đã trả.

Các lỗi thường gặp khi bật keep-alive

  1. Kết nối bị đóng giữa các lần polling — do server hoặc proxy hết timeout; đặt timeout keep-alive lớn hơn 30 giây trong cấu hình client.
  2. Không thấy cải thiện tốc độ — thư viện có thể đã tự bật keep-alive theo mặc định; xác minh bằng công cụ giám sát mạng như Wireshark hoặc tab Network của DevTools.
  3. Lỗi connection refused — pool đã cạn; tăng maxSockets hoặc giảm mức đồng thời.
  4. HTTP/2 không được đàm phán — server không hỗ trợ h2; quay về HTTP/1.1 keep-alive.

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

Nên chọn HTTP/2 hay giữ HTTP/1.1 keep-alive?

Nếu bạn giải tuần tự với ít luồng, HTTP/1.1 keep-alive đã đủ nhanh và đơn giản hơn để triển khai. Chỉ chuyển sang HTTP/2 khi chạy hàng chục luồng song song trở lên.

Cần bao nhiêu kết nối trong pool khi chạy nhiều thread song song?

Khớp pool với số luồng đang chạy. Gói STANDARD ($30/tháng, 15 thread) hợp với pool khoảng 10–15 kết nối; vượt ngưỡng gói ADVANCE (50 thread) thì cân nhắc chuyển hẳn sang HTTP/2.

Proxy có hỗ trợ keep-alive và HTTP/2 không?

Còn tùy proxy. Proxy phải hỗ trợ keep-alive và HTTP/2 thì mới có lợi ích thực sự — một số proxy SOCKS5 không duy trì kết nối liên tục.

Làm sao biết máy chủ CaptchaAI có hỗ trợ HTTP/2?

Chạy curl --http2 https://ocr.captchaai.com/res.php để kiểm tra. Nếu server đàm phán được h2, client HTTP/2 của bạn sẽ được hưởng lợi ngay.

Keep-alive có áp dụng cho callback/webhook thay vì polling không?

Có, nhưng lợi ích rõ nhất vẫn thuộc về polling. Keep-alive giúp request submit nhanh hơn; độ trễ callback phụ thuộc vào server bạn.

Bước tiếp theo

Cắt giảm chi phí kết nối trên mỗi lần giải — lấy API key CaptchaAI của bạn và áp dụng ngay ví dụ Python hoặc Node.js ở trên. Sau đó đọc thêm:

Bài viết liên quan

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