Сводка
У меня есть некоторый код PHP 5.4, который выбирает партию фотографий из Facebook / Instagram параллельно, используя multi curl.Этот код работал годами, и, насколько я могу судить, ничего не изменилось.
Я добавляю несколько запросов curl к запросу 'multi'.Каждый запрос curl получает CURLOPT_TIMEOUT
.Проблема, с которой я сталкиваюсь, заключается в том, что внезапно некоторые из моих запросов не завершаются, пока не истечет этот тайм-аут (независимо от того, какой тайм-аут я установил).
Код
Я делаю что-то вроде этого (упрощенно):
do {
while (CURLM_CALL_MULTI_PERFORM === curl_multi_exec($mh, $running));
// Wait for activity on any curl-connection (optional, reduces CPU)
curl_multi_select($mh);
// a request was just completed -- find out which one
while($done = curl_multi_info_read($mh))
{
$completedCurlRequest = $done['handle'];
//save the file
do_some_work(completedCurlRequest);
curl_multi_remove_handle($mh, $completedCurlRequest);
}
} while ($running);
Я использую этот сценарий для запуска пакетов из примерно 40 параллельных запросов на получение некоторых изображений (из Facebook).Большинство из них занимает около 500 мс.Однако некоторые запросы «зависают» (до CURLOPT_TIMEOUT
) до их поступления.
В основном шаг curl_multi_select
занимает весь тайм-аут.Или, если я удаляю эту строку curl_multi_select
, внешний цикл вращается (сжигание ЦП) до истечения времени ожидания.
Соображения
Это неНеважно, что такое тайм-аут - если я установлю тайм-аут на 30 с, они прибудут через 30 секунд, если я установлю тайм-аут на 1 с, они прибудут через 1 с!
Этодействительно внезапное изменение, которое не связано ни с каким выпуском кода - все работало нормально до 30 января 2019 года, но 31-го внезапно перестало работать.
Это не так простовоспроизвести, так как это влияет только на изображение один раз.Если я повторю это для пакета изображений, который я уже получил, то в следующий раз он будет работать нормально.
Это влияет как на изображения на Facebook, так и на Instagram, поэтому я думаю, что проблема должна заключаться в том, чтобыс моим кодом или моим сервером (а не Facebook или Instagram), поскольку они оба не изменили бы что-то одновременно.
Вопросы
- Я что-то не так делаю при использовании multi-curl, что может вызвать это?(но если так, что изменилось?)
- Изменили ли Facebook и Instagram что-либо, что могло бы вызвать это?
- Возможно, что-то на моем сервере изменилось, чтобы вызвать это?
- Какя могу отладить это?
Обновление Вот что я получаю после медленного запроса, когда он наконец завершается:
INFO
"content_type": "image/jpeg",
"http_code": 200,
"header_size": 377,
"request_size": 180,
"total_time": 15.001012, //<----- Total time == CURLOPT_TIMEOUT
"namelookup_time": 0.007149,
"connect_time": 0.12018,
"pretransfer_time": 0.441911,
"size_download": 40714,
"speed_download": 2714,
"download_content_length": -1, //<------Not set
HEADER
HTTP/2 200
content-type: image/jpeg
x-haystack-needlechecksum: 3529661797
timing-allow-origin: *
access-control-allow-origin: *
cache-control: max-age=1209600, no-transform
date: Mon, 04 Feb 2019 14:04:17 GMT
access-control-expose-headers: X-FB-CEC-Video-Limit
В нем отсутствует заголовок content-length
, но это всегда имеет место при первой загрузке файла.Только 1 или 2 из 50 параллельных запросов являются медленными, но во всех запросах отсутствуют заголовки длины содержимого.
Если я получаю тот же файл снова, это происходит намного быстрее, и я вижу, что длина содержимогоустановите это время
INFO
"download_content_length": 52721,
HEADER
content-length: 52721