Proxy lento: 7 razões para a queda de velocidade e métodos de aceleração
A velocidade da conexão proxy afeta diretamente a eficácia da extração de dados, automação e qualquer tarefa relacionada a solicitações em massa. Quando o proxy funciona lentamente, isso leva ao aumento do tempo de execução dos scripts, timeouts e perda de dados. Neste artigo, analisaremos as razões técnicas para a baixa velocidade e mostraremos maneiras específicas de otimização com exemplos de código e resultados de testes.
Distância geográfica do servidor
A distância física entre seu servidor, o proxy e o recurso de destino é um fator principal de latência. Cada nó adicional na cadeia adiciona milissegundos que se acumulam em solicitações em massa.
Um esquema típico de solicitação através de um proxy é assim: seu servidor → servidor proxy → site de destino → servidor proxy → seu servidor. Se seu parser está na Alemanha, o proxy nos EUA e o site de destino no Japão, os dados percorrem dezenas de milhares de quilômetros.
Exemplo prático: O teste de 1000 solicitações a um site europeu mostrou uma diferença no tempo médio de resposta: através de um proxy na Europa — 180 ms, através de um proxy na Ásia — 520 ms. A diferença de 340 ms por solicitação resulta em 340 segundos (5,6 minutos) para 1000 solicitações.
Solução: Escolha proxies geograficamente próximos ao recurso de destino. Se você está extraindo dados de sites russos — use proxies com IPs russos. Para trabalhar com serviços globais (Google, Amazon), proxies nos EUA ou na Europa Ocidental são ideais, onde estão localizados os principais data centers.
Para proxies residenciais, preste atenção na possibilidade de escolher uma cidade ou região específica, e não apenas o país. A diferença de ping entre proxies de Moscovo e Vladivostok ao acessar um servidor em Moscovo pode chegar a 150-200 ms.
Influência do protocolo na velocidade de transmissão de dados
A escolha do protocolo do proxy afeta significativamente a velocidade. As principais opções são: HTTP/HTTPS, SOCKS4, SOCKS5. Cada um tem suas próprias características de processamento de dados e sobrecargas.
| Protocolo | Velocidade | Sobrecargas | Aplicação |
|---|---|---|---|
| HTTP | Alta | Mínimas | Web scraping, API |
| HTTPS | Média | +15-25% em SSL | Conexões seguras |
| SOCKS4 | Alta | Baixas | Tráfego TCP |
| SOCKS5 | Média-Alta | +5-10% em autenticação | Tráfego universal, UDP |
Proxies HTTP são ideais para web scraping, pois operam na camada de aplicação e podem armazenar dados em cache. SOCKS5 é mais versátil, mas adiciona uma camada adicional de processamento. Para extração simples de HTML, a diferença de velocidade entre HTTP e SOCKS5 pode ser de 10-15%.
Exemplo de configuração em Python (requests):
import requests
# Proxy HTTP - mais rápido para solicitações web
proxies_http = {
'http': 'http://user:pass@proxy.example.com:8080',
'https': 'http://user:pass@proxy.example.com:8080'
}
# SOCKS5 - mais versátil, mas mais lento
proxies_socks = {
'http': 'socks5://user:pass@proxy.example.com:1080',
'https': 'socks5://user:pass@proxy.example.com:1080'
}
# Para web scraping, use HTTP
response = requests.get('https://example.com', proxies=proxies_http, timeout=10)
Se seu provedor oferece ambas as opções, teste-as em tarefas reais. Para trabalhar com proxies de data center, o protocolo HTTP geralmente mostra uma velocidade 12-18% superior em comparação ao SOCKS5 sob a mesma carga.
Sobrecarga do servidor proxy e pools de IP
Quando um servidor proxy atende muitas conexões simultâneas, a velocidade diminui devido a limitações de largura de banda e recursos computacionais. Isso é especialmente crítico para proxies compartilhados, onde um IP é usado por dezenas de clientes.
Um cenário típico de sobrecarga: no início da execução do script, a velocidade é normal (50-100 solicitações por minuto), depois cai drasticamente para 10-15 solicitações. Isso acontece quando o servidor atinge o limite de conexões abertas ou largura de banda.
Sinais de sobrecarga: aumento do tempo de resposta em 200%+, timeouts periódicos, erros "Connection reset by peer", velocidade instável com picos abruptos.
Soluções:
- Use um pool de proxies em vez de um único IP. A rotação entre 10-20 proxies distribui a carga e reduz a probabilidade de bloqueio.
- Limite o número de conexões simultâneas através de um proxy (recomenda-se não mais que 5-10 threads paralelas).
- Para tarefas de alta carga, escolha proxies privados, onde os recursos não são compartilhados com outros usuários.
- Monitore a velocidade em tempo real e exclua automaticamente proxies lentos da rotação.
Exemplo de implementação de um pool com monitoramento de velocidade:
import time
import requests
from collections import deque
class ProxyPool:
def __init__(self, proxies, max_response_time=5.0):
self.proxies = deque(proxies)
self.max_response_time = max_response_time
self.stats = {p: {'total': 0, 'slow': 0} for p in proxies}
def get_proxy(self):
"""Obter o próximo proxy do pool"""
proxy = self.proxies[0]
self.proxies.rotate(-1) # Mover para o final
return proxy
def test_and_remove_slow(self, url='http://httpbin.org/ip'):
"""Testar e remover proxies lentos"""
for proxy in list(self.proxies):
try:
start = time.time()
requests.get(url, proxies={'http': proxy}, timeout=10)
response_time = time.time() - start
self.stats[proxy]['total'] += 1
if response_time > self.max_response_time:
self.stats[proxy]['slow'] += 1
# Remover se mais de 50% das solicitações forem lentas
slow_ratio = self.stats[proxy]['slow'] / self.stats[proxy]['total']
if slow_ratio > 0.5 and self.stats[proxy]['total'] > 10:
self.proxies.remove(proxy)
print(f"Proxy lento removido: {proxy}")
except:
self.proxies.remove(proxy)
# Uso
proxies = [
'http://proxy1.example.com:8080',
'http://proxy2.example.com:8080',
'http://proxy3.example.com:8080'
]
pool = ProxyPool(proxies, max_response_time=3.0)
pool.test_and_remove_slow()
# Trabalhando com o pool
for i in range(100):
proxy = pool.get_proxy()
# Executar solicitação através do proxy
Configurações de conexão e timeouts
Parâmetros de conexão mal configurados são uma causa comum de lentidão aparente do proxy. Timeouts muito longos fazem o script esperar por proxies indisponíveis, enquanto timeouts muito curtos levam a desconexões em conexões normais.
Parâmetros-chave que afetam a velocidade:
- Connection timeout — tempo de espera para estabelecer a conexão. Ideal: 5-10 segundos para proxies residenciais, 3-5 para proxies de data center.
- Read timeout — tempo de espera pela resposta após a conexão ser estabelecida. Depende da tarefa: 10-15 segundos para extração de dados, 30+ para download de arquivos grandes.
- Keep-Alive — reutilização de conexões TCP. Economiza até 200-300 ms em cada solicitação subsequente para o mesmo domínio.
- Connection pooling — pool de conexões abertas. Crítico para alta performance em solicitações em massa.
Configuração otimizada para requests:
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# Criar uma sessão com configurações otimizadas
session = requests.Session()
# Configuração de tentativas
retry_strategy = Retry(
total=3, # Máximo de 3 tentativas
backoff_factor=0.5, # Atraso entre tentativas: 0.5, 1, 2 segundos
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["GET", "POST"]
)
# Adaptador com pool de conexões
adapter = HTTPAdapter(
max_retries=retry_strategy,
pool_connections=10, # Pool para 10 hosts
pool_maxsize=20 # Máximo de 20 conexões
)
session.mount("http://", adapter)
session.mount("https://", adapter)
# Configuração do proxy
session.proxies = {
'http': 'http://user:pass@proxy.example.com:8080',
'https': 'http://user:pass@proxy.example.com:8080'
}
# Solicitação com timeouts otimizados
# (connection_timeout, read_timeout)
response = session.get(
'https://example.com',
timeout=(5, 15), # 5 seg para conexão, 15 para leitura
headers={'Connection': 'keep-alive'} # Reutilização da conexão
)
O uso de sessões com Keep-Alive ao extrair 1000 páginas de um único site acelera o trabalho em 30-40% em comparação com a criação de uma nova conexão para cada solicitação. A economia de tempo na configuração da conexão TCP e no handshake SSL é crítica em operações em massa.
Sobrecargas de criptografia e SSL/TLS
Conexões HTTPS requerem recursos computacionais adicionais para criptografar/descriptografar dados e realizar o handshake SSL/TLS. Ao trabalhar através de um proxy, isso acontece duas vezes: entre você e o proxy, e entre o proxy e o servidor de destino.
Sobrecargas típicas de SSL/TLS:
- Handshake inicial: 150-300 ms (depende do algoritmo e da distância)
- Criptografia/descriptografia de dados: +10-20% ao tempo de transmissão
- Carga adicional na CPU do servidor proxy em tráfego alto
Maneiras de otimização:
1. Use TLS Session Resumption
Permite reutilizar os parâmetros da sessão SSL e pular o handshake completo. Economia de até 200 ms em cada conexão subsequente.
Em Python, isso funciona automaticamente ao usar requests.Session(), mas certifique-se de não criar uma nova sessão para cada solicitação.
2. Prefira TLS 1.3
TLS 1.3 requer apenas uma viagem de ida e volta para o handshake em vez de duas no TLS 1.2. Isso reduz o tempo de estabelecimento da conexão em 30-50%.
Certifique-se de que sua biblioteca (OpenSSL, urllib3) suporta TLS 1.3 e que não está desativada nas configurações.
3. Para tarefas internas, considere HTTP
Se você está extraindo dados públicos que não contêm informações confidenciais e o site está disponível via HTTP, use uma conexão não criptografada. Isso proporcionará um aumento de velocidade de 15-25%.
Ao trabalhar com proxies móveis, onde a conexão pode ser mais lenta, as sobrecargas de SSL se tornam ainda mais evidentes. Em testes, a diferença entre solicitações HTTP e HTTPS através de proxies 4G foi de 280 ms em média.
Resolução DNS e cache
Cada solicitação a um novo domínio requer resolução DNS — a conversão do nome de domínio em um endereço IP. Sem cache, isso adiciona 20-100 ms a cada solicitação, e em um servidor DNS lento, a latência pode chegar a 500+ ms.
Quando você trabalha através de um proxy, as solicitações DNS podem ser executadas em três lugares:
- Do seu lado (o cliente resolve o domínio e passa o IP para o proxy)
- No servidor proxy (SOCKS5, HTTP CONNECT — o proxy recebe o domínio e resolve por conta própria)
- No servidor de destino (raramente, em configurações específicas)
Para proxies SOCKS5, a resolução DNS geralmente ocorre no lado do servidor proxy, o que pode ser mais lento se o provedor de proxy tiver servidores DNS ruins. Proxies HTTP costumam resolver no lado do cliente.
Métodos para acelerar DNS:
import socket
from functools import lru_cache
# Cache de resolução DNS no lado do cliente
@lru_cache(maxsize=256)
def cached_resolve(hostname):
"""Cache de resultados de solicitações DNS"""
try:
return socket.gethostbyname(hostname)
except socket.gaierror:
return None
# Uso
hostname = 'example.com'
ip = cached_resolve(hostname)
if ip:
# Usar IP diretamente nas solicitações
url = f'http://{ip}/path'
headers = {'Host': hostname} # Especificar o host original no cabeçalho
Uma abordagem alternativa é usar servidores DNS públicos rápidos em nível de sistema:
- Google DNS: 8.8.8.8, 8.8.4.4
- Cloudflare DNS: 1.1.1.1, 1.0.0.1
- Quad9: 9.9.9.9
No Linux, a configuração é feita através de /etc/resolv.conf:
nameserver 1.1.1.1
nameserver 8.8.8.8
options timeout:2 attempts:2
Para scripts Python com muitos domínios, recomenda-se o pré-aquecimento do cache DNS:
import concurrent.futures
import socket
def warmup_dns_cache(domains):
"""Pré-resolver uma lista de domínios"""
def resolve(domain):
try:
socket.gethostbyname(domain)
except:
pass
with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
executor.map(resolve, domains)
# Lista de domínios para extração
domains = ['site1.com', 'site2.com', 'site3.com']
warmup_dns_cache(domains)
# Agora o DNS já está no cache, as solicitações serão mais rápidas
Qualidade da infraestrutura do provedor
A velocidade do proxy depende diretamente da qualidade do hardware e das conexões do provedor. Proxies baratos frequentemente operam em servidores sobrecarregados com interfaces de rede lentas e hardware desatualizado.
Parâmetros críticos da infraestrutura:
| Parâmetro | Ruim | Bom | Impacto na velocidade |
|---|---|---|---|
| Largura de banda do canal | 100 Mbit/s | 1+ Gbit/s | Crítico ao carregar arquivos |
| Processador do servidor | 2-4 núcleos | 8+ núcleos | Impacta no processamento de SSL/TLS |
| RAM | 4-8 GB | 16+ GB | Cache e bufferização |
| Uptime | <95% | 99%+ | Estabilidade das conexões |
| Roteamento | Padrão | Otimizado BGP | Latência e perda de pacotes |
Provedores com infraestrutura própria (não revendedores) geralmente garantem uma velocidade consistentemente alta. Eles controlam toda a pilha: do hardware às configurações do equipamento de rede.
Sinais de uma infraestrutura de qualidade:
- Velocidade estável ao longo do dia (variações não superiores a 15-20% da média)
- Baixo jitter (variação de latência) — menos de 10 ms
- Mínima perda de pacotes (<0.1%)
- Resposta rápida do suporte técnico a problemas (importante para tarefas empresariais)
- Informações transparentes sobre a localização dos servidores e características dos canais
Para tarefas críticas, recomenda-se testar proxies em condições o mais próximas possível das reais. Adquira acesso de teste por 1-3 dias e execute scripts reais monitorando todas as métricas.
Metodologia de teste de velocidade do proxy
Testes adequados ajudam a identificar gargalos e comparar objetivamente diferentes provedores. Um simples speedtest não é suficiente — é necessário medir parâmetros importantes para suas tarefas.
Métricas-chave para medir:
- Latência — tempo de ida e volta de um pacote. Crítico para tarefas com muitas pequenas solicitações.
- Throughput — volume de dados por unidade de tempo. Importante para upload de arquivos, imagens.
- Tempo de conexão — tempo para estabelecer a conexão. Mostra a eficiência para solicitações únicas.
- Taxa de sucesso — porcentagem de solicitações bem-sucedidas. Abaixo de 95% — um indicador ruim.
- Jitter — variação de latência. Alto jitter (>50 ms) indica instabilidade do canal.
Script abrangente para testes:
import time
import requests
import statistics
from concurrent.futures import ThreadPoolExecutor, as_completed
def test_proxy_performance(proxy, test_url='https://httpbin.org/get', requests_count=50):
"""
Teste abrangente de proxy
Args:
proxy: URL do proxy
test_url: URL para teste
requests_count: Número de solicitações de teste
Returns:
dict com métricas
"""
results = {
'latencies': [],
'connection_times': [],
'total_times': [],
'successes': 0,
'failures': 0,
'errors': []
}
session = requests.Session()
session.proxies = {'http': proxy, 'https': proxy}
def single_request():
try:
start = time.time()
response = session.get(
test_url,
timeout=(5, 15),
headers={'Connection': 'keep-alive'}
)
total_time = time.time() - start
if response.status_code == 200:
results['successes'] += 1
results['total_times'].append(total_time)
# Estimativa aproximada de latência
results['latencies'].append(total_time / 2)
else:
results['failures'] += 1
except Exception as e:
results['failures'] += 1
results['errors'].append(str(e))
# Execução paralela de solicitações
with ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(single_request) for _ in range(requests_count)]
for future in as_completed(futures):
future.result()
# Cálculo de estatísticas
if results['total_times']:
metrics = {
'proxy': proxy,
'total_requests': requests_count,
'success_rate': (results['successes'] / requests_count) * 100,
'avg_response_time': statistics.mean(results['total_times']),
'median_response_time': statistics.median(results['total_times']),
'min_response_time': min(results['total_times']),
'max_response_time': max(results['total_times']),
'stdev_response_time': statistics.stdev(results['total_times']) if len(results['total_times']) > 1 else 0,
'jitter': statistics.stdev(results['latencies']) if len(results['latencies']) > 1 else 0,
'failures': results['failures']
}
return metrics
else:
return {'proxy': proxy, 'error': 'Todas as solicitações falharam'}
# Teste
proxy = 'http://user:pass@proxy.example.com:8080'
metrics = test_proxy_performance(proxy, requests_count=100)
print(f"Proxy: {metrics['proxy']}")
print(f"Taxa de sucesso: {metrics['success_rate']:.1f}%")
print(f"Tempo médio de resposta: {metrics['avg_response_time']*1000:.0f} ms")
print(f"Mediana: {metrics['median_response_time']*1000:.0f} ms")
print(f"Jitter: {metrics['jitter']*1000:.0f} ms")
print(f"Desvio padrão: {metrics['stdev_response_time']*1000:.0f} ms")
Para resultados mais precisos, teste em diferentes horários do dia (manhã, tarde, noite) e em diferentes sites de destino. A velocidade pode variar significativamente dependendo da geografia e da carga na rede.
Dica: Crie uma linha de base (baseline) — teste uma conexão direta sem proxy. Isso fornecerá um ponto de referência para avaliar as sobrecargas do proxy. Sobrecargas normais: 50-150 ms para proxies de qualidade.
Otimização abrangente: checklist
A aplicação de todos os métodos descritos em conjunto gera um efeito cumulativo. Aqui está um plano passo a passo para otimizar a velocidade de operação através de proxies:
Passo 1: Escolha e configuração do proxy
- Escolha proxies geograficamente próximos aos recursos de destino
- Para web scraping, use o protocolo HTTP em vez de SOCKS5
- Prefira proxies privados para tarefas de alta carga
- Certifique-se de que o provedor suporta TLS 1.3
Passo 2: Otimização do código
- Use
requests.Session()com Keep-Alive - Configure o connection pooling (10-20 conexões)
- Defina timeouts ideais: 5-10 seg para conexão, 15-30 para leitura
- Implemente lógica de retry com exponential backoff
- Cache a resolução DNS
Passo 3: Gerenciamento do pool de proxies
- Crie um pool de 10-50 proxies para rotação
- Limite o número de solicitações simultâneas através de um proxy (5-10 threads)
- Monitore a velocidade e exclua automaticamente proxies lentos
- Use sessões fixas para tarefas que requerem a manutenção do IP
Passo 4: Otimização do sistema
- Configure servidores DNS rápidos (1.1.1.1, 8.8.8.8)
- Aumente os limites de arquivos abertos no SO (ulimit -n 65535)
- Para Linux: otimize os parâmetros TCP do kernel
- Use SSD para cache, se estiver lidando com grandes volumes de dados
Passo 5: Monitoramento e teste
- Teste regularmente a velocidade do proxy (mínimo uma vez por semana)
- Registre métricas: tempo de resposta, taxa de sucesso, erros
- Compare o desempenho de diferentes provedores
- Configure alertas quando a velocidade cair abaixo de um limite
Exemplo de configuração otimizada para produção:
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from collections import deque
import time
class OptimizedProxyPool:
def __init__(self, proxies_list):
self.proxies = deque(proxies_list)
self.session = self._create_optimized_session()
self.stats = {p: {'requests': 0, 'avg_time': 0} for p in proxies_list}
def _create_optimized_session(self):
"""Criar uma sessão otimizada"""
session = requests.Session()
# Estratégia de retry
retry = Retry(
total=3,
backoff_factor=0.3,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["GET", "POST", "PUT"]
)
# Adaptador com connection pooling
adapter = HTTPAdapter(
max_retries=retry,
pool_connections=20,
pool_maxsize=50,
pool_block=False
)
session.mount("http://", adapter)
session.mount("https://", adapter)
# Cabeçalhos Keep-Alive
session.headers.update({
'Connection': 'keep-alive',
'Keep-Alive': 'timeout=60, max=100'
})
return session
def get_best_proxy(self):
"""Obter o proxy com melhor desempenho"""
# Classificação por velocidade média
sorted_proxies = sorted(
self.stats.items(),
key=lambda x: x[1]['avg_time'] if x[1]['requests'] > 0 else float('inf')
)
return sorted_proxies[0][0] if sorted_proxies else self.proxies[0]
def request(self, url, method='GET', **kwargs):
"""Executar solicitação através do proxy otimizado"""
proxy = self.get_best_proxy()
self.session.proxies = {'http': proxy, 'https': proxy}
start = time.time()
try:
response = self.session.request(
method,
url,
timeout=(5, 15), # conexão, leitura
**kwargs
)
# Atualizar estatísticas
elapsed = time.time() - start
stats = self.stats[proxy]
stats['avg_time'] = (
(stats['avg_time'] * stats['requests'] + elapsed) /
(stats['requests'] + 1)
)
stats['requests'] += 1
return response
except Exception as e:
# Em caso de erro, mover o proxy para o final da fila
self.proxies.remove(proxy)
self.proxies.append(proxy)
raise e
# Uso
proxies = [
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080'
]
pool = OptimizedProxyPool(proxies)
# Executando solicitações
for url in ['https://example.com', 'https://example.org']:
try:
response = pool.request(url)
print(f"Sucesso: {url}, status: {response.status_code}")
except Exception as e:
print(f"Erro: {url}, {e}")
A aplicação desta checklist permite aumentar a velocidade de operação através de proxies em 2-3 vezes em comparação com configurações básicas. Em projetos reais de extração de dados, isso reduz o tempo de execução de horas para minutos.
Conclusão
O funcionamento lento do proxy é um problema solucionável, se você entender as razões técnicas e aplicar os métodos corretos de otimização. Os principais fatores de velocidade incluem: proximidade geográfica, escolha do protocolo, qualidade da infraestrutura do provedor e configuração correta do código do cliente.
Uma abordagem abrangente para otimização inclui a combinação de várias técnicas para alcançar o melhor desempenho possível.