В мультиинтерфейсе cURL иногда возникает ошибка "Тайм-аут соединения", когда total_time слишком много меньше, чем опция тайм-аута

Я работаю над проектом, который собирает и тестирует публичные / бесплатные прокси-серверы, и иногда замечал при последующих запросах в группе сообщение об ошибке "Тайм-аут соединения" с total_time очень меньшим CURLOPT_CONNECTTIMEOUT опция при использовании мультиинтерфейса cURL для одновременного выполнения множества запросов, что никогда не происходит, если я выполняю каждый запрос в одиночку с помощью cURL только без мультиинтерфейса.

Вот класс, который я сделал для тестирования этого поведения, я не мог включить его здесь для ограничения длины сообщения, вы можете найти его по адресу https://github.com/accountantM/CurlMultiTimeoutBugTester

вы можете использовать его как

$curlTester = new CurlMultiTimeoutBugTester();
$report = $curlTester->test($url, 2, 1000);
echo $report;
exit;

Иногда эта ошибка может возникнуть, в то время как в других случаях она работает нормально для всех запросов с нормальным total_time это так же, как CURLOPT_CONNECTTIMEOUT Вот пример выходного отчета, который показывает проблему.

нормальный таймаут в то время как CURLOPT_CONNECTTIMEOUT установлен на 2 секунды, как это

84.241.19.214:4145 err:"Connection timed out after 2005 milliseconds", total_time:2.364736

нормальное соединение отказано, вот так

83.219.1.80:56004 err:"Failed to connect to 83.219.1.80 port 56004: Connection refused", total_time:0.000107

Но это не нормально

35.196.70.16:80 err:"Connection time-out", total_time:0.00033  <=================   BUG

Если вы подключаетесь к каждому прокси из них наедине с CURLOPT_CONNECTTIMEOUT если установить значение 2 секунды, вы никогда не получите эту ошибку при последующих запросах, некоторые из них работают, а некоторые воспользуются возможностью и попытаются подключиться в течение 2 секунд, а затем потерпят неудачу, но эта ошибка "total_time очень small than timeout" происходит только с cURL multi интерфейс.

Пожалуйста, помогите мне, я новичок в cURL, и уже 3 дня пытаюсь понять, что происходит, я перепробовал почти все варианты, которые могут быть связаны CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPT_DNS_CACHE_TIMEOUT, CURLOPT_NOSIGNAL, CURLOPT_CONNECTTIMEOUT_MS, CURLOPT_NOSIGNAL, CURLOPT_PIPEWAIT, CURLMOPT_PIPELINING, CURLOPT_TCP_FASTOPEN, CURLOPT_MAXCONNECTS, CURLMOPT_MAXCONNECTS, CURLMOPT_MAX_HOST_CONNECTIONS Я тоже пытался убрать звонок curl_multi_select($mh) и цикл с curl_multi_exec($mh, $active) только, но та же проблема показывает иногда:( .

К сожалению, проверьте этот вопрос и ответы на него, и вы поймете, что выполнение асинхронных HTTP-запросов все еще является большой проблемой в PHP:(


ОБНОВИТЬ

маленький TOTAL_TIME проблема была исправлена

0 ответов

Старайтесь не иметь 400 открытых соединений в одном потоке. Или даже процесс, в этом отношении. Возможно, вы перегружаете прокси-серверы, поэтому они могут занести вас в черный список (безопасность отказа в обслуживании). Или ваша исходящая сеть может ограничивать количество открытых соединений.

Мне кажется, что у вас нет проблем с самим curl, но вы делаете слишком много подключений одновременно с прокси-серверами, если в соединениях отказано. Вы можете быть в черном списке навсегда или в течение некоторого периода.

Проверьте это, запустив свой curl с текущего IP-адреса, и выполните stat: сколько соединений было установлено, сколько отказано, сколько истекло. Сделайте это несколько раз и наберите в среднем. Затем измените сервер на другой, который имеет другой IP-адрес, и проверьте, какая у вас там статистика. При первом запуске у вас должна быть намного лучшая статистика, которая, вероятно, если вы повторите тест на новом IP, станет только хуже. Хорошей идеей может быть не использовать весь пул прокси-серверов для подключения к статистике, а выбрать из них срез, проверить фактический IP-адрес и повторить эту проверку нового IP-адреса, поэтому, если причина в том, что вы злоупотребляете сервисом, вы не попадете в черный список все прокси, но все еще будут иметь следующую группу "нетронутых" прокси, чтобы проверить их на новом IP, если это действительно так. Помните, что даже если IP-адреса прокси находятся в разных местах, они могут принадлежать одному и тому же поставщику услуг. Вероятно, у него есть один список злоупотреблений для всех их прокси-серверов, поэтому, если вас плохо видят количество запросов, которые вы делаете в одной стране, вас могут заблокировать и в другой стране, даже до того, как вы подключитесь к прокси-серверу другой страны.

Если вы все еще хотите проверить, не скручивается ли это, вы можете настроить тестовую среду с несколькими подачами. Эту среду тестирования вы можете передать сопровождающему curl, чтобы он мог воспроизвести ошибку. Вы можете использовать docker и создавать 10, 20 или 100 прокси-серверов и подключаться к ним, чтобы увидеть, есть ли у curl проблема или нет.

вам понадобится докер, его можно установить на Win/Mac/Linux
один из прокси-изображений для создания прокси
создать сетевой учебник для контейнеров (мост должен быть в порядке)
подключить контейнеры к сети --network
хорошо установить для каждого прокси-контейнера свой --ip
Сделайте так, чтобы для каждого прокси-контейнера можно было читать конфигурацию и записывать журнал ошибок (чтобы вы могли понять, почему они отключились, если это произойдет), с помощью mountig error log/config files/direcotires с --volume
и все прокси-контейнеры должны быть запущены

Вы можете подключиться к прокси, который работает внутри контейнера двумя способами. если вы хотите, чтобы curl находился за пределами этих контейнеров, вам нужно открыть с помощью -p порты этих прокси-серверов из контейнера во внешний мир (curl в вашем случае).

или же

Вы можете использовать другой образ контейнера с linux + curl. Например, Alpine linux + curl и подключите его к той же сети, что и с прокси. Если вы делаете это, вам не нужно публиковать (выставлять) порты прокси и не нужно думать о том, какой номер порта прокси я должен предоставить для этого конкретного прокси.

на каждом шаге вы можете выполнить команду

docker ps -a

чтобы увидеть все контейнеры и их статус.

остановить и удалить все контейнеры (не изображения, из которых они исходят, а запущенные контейнеры) на случай, если у вас возникли ошибки с контейнером, который вышел.

docker stop $(docker ps -aq) && docker rm $(docker ps -aq)

или остановить и удалить из списка тот или иной контейнер

docker stop <container-id>
docker rm <container-id>

чтобы увидеть все контейнеры, которые подключены к мостовой сети (по умолчанию)

docker network inspect bridge

Если вы подтвердите, что действительно существует проблема с подключением к прокси, которые находятся на вашем локальном компьютере, то это то, что сопровождающий curl может воспроизвести.

например, поместите все команды, как указано выше, чтобы создать все прокси, подключить их к сети и т. д. в файле replicate.sh сценарий, начинающийся с

#!/bin/sh

and your comands here

сохраните этот файл и выполните команду

chmod +x ./replicate.sh

сделать его исполняемым.

Вы можете запустить его, чтобы проверить, все ли работает как положено

./replicate.sh

и отправьте сопровождающего curl для репликации среды, в которой у вас возникла проблема.

Если вам не нравится помещать множество команд, таких как doker, для запуска прокси, вы можете вместо этого использовать docker compose, что позволяет вам определять всю среду тестирования в одном файле.

Если вы запускаете много контейнеров, вы можете ограничить ресурсы, например, память, которую использует каждый из них, может помочь вам в случае такого количества прокси

Другие вопросы по тегам