【发布时间】:2019-06-26 08:05:47
【问题描述】:
总结
我有一些 PHP 5.4 代码,它使用 multi curl 并行获取一批 Facebook/Instagram 照片。这段代码已经运行了多年,据我所知没有任何改变。
我将多个 curl 请求添加到“多”请求中。每个 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 行,外部循环会旋转(燃烧 CPU)直到超时。
注意事项
超时时间无关紧要 - 如果我将超时时间设置为 30 秒, 他们在 30 秒后到达,如果我将超时设置为 1 秒,他们就会到达 1秒后!
这是一个非常突然的变化,与任何代码都没有关联 发布 - 在 2019 年 1 月 30 日之前一切正常,但在 31 号突然停止工作。
这不容易重现,因为它只影响图像一次。如果我 对我已经获取的一批图像重复它,它工作正常 下一轮。
它同时影响 Facebook 和 Instagram 图片,所以我认为这个问题 必须与我的代码或我的服务器(而不是 Facebook 或 Instagram),因为他们都不会改变一些东西 同时。
问题
- 我在使用 multi-curl 时是否做错了可能导致这种情况的事情? (但如果是这样,有什么变化?)
- Facebook 和 Instagram 是否更改了可能导致此问题的任何内容?
- 我的服务器上的某些内容是否已更改以触发此问题?
- 如何调试?
更新 这是我最终完成时从缓慢的请求中得到的结果:
信息
"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
标题
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 标头,但第一次获取文件时似乎总是如此。 50 个并行请求中只有 1 或 2 个速度较慢,但所有请求都缺少其内容长度标头。
如果我再次获取相同的文件,它会快得多,而且我确实看到这次设置了内容长度
信息
"download_content_length": 52721,
标题
content-length: 52721
【问题讨论】:
-
they wouldn't have both changed something simultaneously.- 是的,很有可能。 Facebook 拥有 Instagram,它们很可能在同一个图像 CDN 堆栈上运行,这可能与您的问题有关 - 当这种情况发生时,该 curl 句柄是否收到Content-Length标头?你也使用 CURLOPT_ENCODING 吗?在这种情况下,服务器选择了什么编码? (又名响应的Content-Encoding标头包含什么?如果该标头是结果中的总统) -
谢谢@hanshenrik,不,我没有设置 CURLOPT_ENCODING。我将转储响应中的所有字段,但我到底在寻找什么?
-
您正在寻找
Content-Length标头,如果缺少该标头,它可以解释为什么下载速度如此之慢。还要检查这是否有所不同:curl_setopt($ch,CURLOPT_ENCODING,'identity'); -
嗨@hanshenrik - 我已经根据你的建议更新了我的问题。确实缺少内容长度,但成功请求也是如此。我已经尝试过您的 CURLOPT_ENCODING 建议,但这并没有改变任何东西。也许你可以给我一些关于下一步要尝试什么的提示?
标签: php curl php-5.4 curl-multi