Explainers

Влияние разрешения DNS на производительность API CAPTCHA

Если ваш HTTP-клиент держит keep-alive-соединение с ocr.captchaai.com, DNS почти не участвует в задержке решения CAPTCHA — резолвинг происходит один раз, а дальше запросы идут по уже открытому TCP-соединению. Проблема начинается там, где соединение создаётся заново под каждый запрос: холодный старт бессерверной функции, короткоживущий воркер парсинга, медленный DNS-резолвер провайдера. В таких сценариях DNS способен добавить от 5 до 200 мс к каждому из 5–7 HTTP-запросов, из которых складывается одно решение CAPTCHA. Разберёмся, когда это действительно ощутимо и как убрать задержку в Python и Node.js.

Когда DNS-резолвинг реально тормозит решение CAPTCHA

DNS становится узким местом в четырёх типичных ситуациях:

  • Новое соединение на каждый запрос — нет Session в Python или keep-alive-агента в Node.js, поэтому TCP-хендшейк и DNS-резолвинг повторяются заново при каждом вызове.
  • Холодный старт контейнера или бессерверной функции — на свежем экземпляре нет ни кеша DNS, ни открытого соединения.
  • Медленный DNS-провайдер — DNS хостинга по умолчанию, без локального кеша, резолвит заметно дольше, чем 1.1.1.1 или 8.8.8.8.
  • Массовый параллельный запуск воркеров — десятки исполнителей стартуют одновременно, и каждый резолвит DNS с нуля.

Пример из практики: если воркеры парсинга разворачиваются в облачных регионах Европы (Франкфурт, Амстердам) или Центральной Азии, путь до ближайшего DNS-резолвера обычно длиннее, чем из США, — 30–60 мс на один резолв не редкость. При тарифе с фиксированным числом потоков — например, BASIC ($15/мес, 5 потоков) или ADVANCE ($90/мес, 50 потоков) — лишние миллисекунды на резолвинг умножаются на количество параллельных потоков и снижают ту пропускную способность, за которую вы уже заплатили.

Что происходит внутри одного решения CAPTCHA

Одно решение CAPTCHA — это 5–7 HTTP-запросов: одна отправка задачи и 4–6 опросов результата через res.php. Вот как разные стратегии резолвинга DNS влияют на итоговую задержку:

Сценарий DNS-резолвингов Задержка
Без кеша, медленный DNS (200 мс на запрос) 7 1400 мс
DNS-кеш на уровне ОС (резолвинг только на первом вызове) 1 200 мс
Keep-alive соединение (0 новых резолвингов) 0 0 мс
Предварительное разрешение DNS + keep-alive 0 0 мс

Главный вывод: если keep-alive уже включён, одно и то же TCP-соединение переиспользует ранее разрешённый IP-адрес, и DNS перестаёт быть проблемой. Резолвинг имеет значение ровно там, где соединения создаются заново под каждый запрос.

Оптимизация DNS в Python

Три шага: сначала измерить, затем закешировать адрес заранее, и только если этого мало — сменить резолвер.

Самый быстрый способ убедиться, что DNS вообще влияет на ваш кейс, — замерить время двух последовательных вызовов getaddrinfo:

import socket
import time

# Measure DNS resolution time
hostname = "ocr.captchaai.com"

start = time.time()
ip = socket.getaddrinfo(hostname, 443)
first_resolve = time.time() - start

start = time.time()
ip = socket.getaddrinfo(hostname, 443)
second_resolve = time.time() - start

print(f"First resolve: {first_resolve*1000:.1f}ms")
print(f"Second resolve: {second_resolve*1000:.1f}ms (OS cached)")

Если разница между первым и вторым замером заметна — резолвите ocr.captchaai.com один раз при старте процесса и держите сессию с keep-alive открытой:

import os
import socket
import requests
from urllib3.util.connection import create_connection

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

# Pre-resolve the API hostname
CAPTCHAAI_IP = socket.getaddrinfo("ocr.captchaai.com", 443)[0][4][0]
print(f"Resolved ocr.captchaai.com to {CAPTCHAAI_IP}")

# Patch connection to use cached IP
DNS_CACHE = {"ocr.captchaai.com": CAPTCHAAI_IP}

class CachedHTTPAdapter(requests.adapters.HTTPAdapter):
    def send(self, request, **kwargs):
        return super().send(request, **kwargs)

# Use with Session for fastest resolution
session = requests.Session()
session.headers.update({"Connection": "keep-alive"})

# The session already maintains keep-alive, so DNS is resolved once
# For the first request, the OS cache handles subsequent lookups
resp = session.get("https://ocr.captchaai.com/res.php", params={
    "key": API_KEY, "action": "getbalance", "json": "1",
})
print(f"Balance: {resp.json()}")

Если и после этого задержка остаётся, переключите систему или приложение на быстрый публичный DNS:

# For systems where you control DNS configuration:
# /etc/resolv.conf (Linux) or system DNS settings
# Recommended: Cloudflare (1.1.1.1) or Google (8.8.8.8)

# In Python, you can also use dnspython for explicit resolution
import dns.resolver

resolver = dns.resolver.Resolver()
resolver.nameservers = ["1.1.1.1", "8.8.8.8"]

answers = resolver.resolve("ocr.captchaai.com", "A")
for answer in answers:
    print(f"Resolved: {answer}")

Оптимизация DNS в Node.js

Та же логика, что и в Python: сначала замерить, затем убрать резолвинг из горячего пути через keep-alive и предварительное разрешение. Тест на резолвинг — через встроенный модуль dns:

const dns = require('dns');
const { performance } = require('perf_hooks');

const hostname = 'ocr.captchaai.com';

// First resolution
const start1 = performance.now();
dns.lookup(hostname, (err, address) => {
  const time1 = performance.now() - start1;
  console.log(`First resolve: ${time1.toFixed(1)}ms → ${address}`);

  // Second resolution (OS cached)
  const start2 = performance.now();
  dns.lookup(hostname, (err2, address2) => {
    const time2 = performance.now() - start2;
    console.log(`Second resolve: ${time2.toFixed(1)}ms → ${address2}`);
  });
});

Комбинация предварительного резолвинга и keep-alive-агента убирает DNS из горячего пути полностью:

const dns = require('dns');
const https = require('https');
const axios = require('axios');

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

// Pre-resolve and cache
let cachedIP = null;

async function preResolve() {
  return new Promise((resolve, reject) => {
    dns.lookup('ocr.captchaai.com', (err, address) => {
      if (err) reject(err);
      cachedIP = address;
      console.log(`Cached IP: ${cachedIP}`);
      resolve(address);
    });
  });
}

// Use keep-alive agent (DNS resolved once per connection)
const agent = new https.Agent({
  keepAlive: true,
  maxSockets: 20,
  keepAliveMsecs: 60000,
});

const api = axios.create({
  baseURL: 'https://ocr.captchaai.com',
  httpsAgent: agent,
  timeout: 30000,
});

(async () => {
  await preResolve();
  const resp = await api.get('/res.php', {
    params: { key: API_KEY, action: 'getbalance', json: '1' },
  });
  console.log(`Balance: ${resp.data}`);
})();

DNS в бессерверных и контейнерных средах

В AWS Lambda, Google Cloud Functions и контейнерах Docker поведение DNS-кеша отличается от классического сервера:

Среда Поведение DNS-кеша Рекомендация
AWS Lambda Кешируется в рамках контекста выполнения, теряется при холодном старте Разрешайте адрес заранее в инициализации обработчика
Google Cloud Functions Кешируется в рамках экземпляра Разрешайте адрес заранее в глобальной области
Docker По умолчанию использует DNS хоста Настройте --dns 1.1.1.1
Kubernetes CoreDNS с настраиваемым кешем Установите ndots: 1 в DNS-конфигурации пода

Диагностика типичных проблем

Симптом почти всегда указывает на конкретную причину — и на конкретное исправление:

Симптом Причина Что делать
Первый запрос к API медленный, остальные быстрые DNS-резолвинг произошёл только на первом вызове Это нормально при OS-кешировании — используйте keep-alive
Все запросы медленные (+100 мс и больше) DNS не кешируется, резолвер медленный Переключитесь на 1.1.1.1 или 8.8.8.8
Случайные всплески задержки Истёк TTL записи в DNS-кеше Увеличьте локальный TTL кеша или резолвите адрес заранее
Холодный старт контейнера медленный На новом экземпляре нет кешированного DNS Резолвите адрес заранее в коде инициализации

Частые вопросы

Сколько DNS-резолвингов реально происходит при одном решении CAPTCHA?

Без кеша — до семи: один при отправке задачи и по одному на каждый опрос res.php. С включённым keep-alive обычно происходит один резолвинг на всё время жизни соединения, а не на каждый запрос.

Обязательно ли переключаться на сторонний DNS-резолвер, если я уже использую keep-alive?

Нет. Если соединение постоянное, DNS резолвится один раз при его установке, и выбор резолвера почти не влияет на итоговую задержку. Переход на 1.1.1.1 или 8.8.8.8 даёт эффект там, где соединения создаются заново под каждый запрос.

Как задержка DNS сказывается на тарифе с фиксированным числом потоков?

Каждый поток, который ждёт резолвинга DNS вместо отправки запроса, простаивает впустую. На тарифах вроде BASIC (5 потоков) или STANDARD ($30/мес, 15 потоков) это заметнее, чем на ENTERPRISE ($300/мес, 200 потоков), где издержки размываются на больший пул, — но принцип один: предварительное разрешение и keep-alive увеличивают полезную пропускную способность без смены тарифа.

Стоит ли беспокоиться о DNS, если парсинг идёт через прокси-серверы?

Да, но с поправкой: DNS для самого прокси и DNS для ocr.captchaai.com резолвятся отдельно. Настройте keep-alive и предварительное разрешение для соединения с CaptchaAI API независимо от того, как настроен прокси для целевого сайта.

Следующие шаги

Комментарии для этой статьи отключены.