В мультиинтерфейсе 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, что позволяет вам определять всю среду тестирования в одном файле.
Если вы запускаете много контейнеров, вы можете ограничить ресурсы, например, память, которую использует каждый из них, может помочь вам в случае такого количества прокси