亚马逊 AWSSDKforPHP 太慢了。

5

Amazon AWSSDKforPHP太慢了

你好,

我正在使用Amazon AWSSDKforPHP将我的Web应用程序连接到S3。但是,与该过程或向服务发出请求有关的问题使其变得太慢。

例如,我有以下代码:

// Iterate an array of user images
foreach($images as $image){
    // Return the Bucket URL for this image
    $urls[] = $s3->get_object_url($bucket, 'users/'.trim($image).'.jpg', '5 minutes');
}

假设$images是用户图片数组,这将返回一个名为$urls的数组,其中包含(如其名称所示)具有5分钟凭据的图片URL。对于35张图片,此请求至少需要6秒钟,这很好。但是......当图片不存在于存储桶中时,我想为用户分配默认图片,例如“images/noimage.png”。

以下是代码:
// Iterate an array of user images
foreach($images as $image){

    // Check if the object exists in the Bucket
    if($s3->if_object_exists($bucket, 'users/'.trim($image).'.jpg')){
        // Return the Bucket URL for this image
        $urls[] = $s3->get_object_url($bucket, 'users/'.trim($image).'.jpg', '5 minutes');
    } else { 

        // Return the default image
        $urls[] = 'http://www.example.com/images/noimage.png';
    }

}

这个条件可以正常工作,但速度非常慢。使用"$s3->if_object_exists()"这个条件,在有35张图片的情况下,脚本至少需要40秒的时间!

我已经修改了我的脚本,并使用cURL发送请求:

// Iterate an array of user images
foreach($images as $image){

    // Setup cURL
    $ch = curl_init($s3->get_object_url($bucket, 'users/'.trim($image).'.jpg', '1 minutes') );
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    // Get Just the HTTP response code
    $res = curl_getinfo($ch,CURLINFO_HTTP_CODE);

    if($res == 200){ //the image exists
        $urls[] = $s3->get_object_url($bucket, 'users/'.trim($image).'.jpg', '5 minutes');
    }else{ // The response is 403
        $urls[] = 'http://www.example.com/images/noimage.png';
    }
}

这个修改后的脚本需要花费16到18秒的时间。这是一个很大的时间差异,但仍然需要很长时间 :(。

请帮忙看看有没有任何帮助,非常感谢。

谢谢。


3
我不了解S3 API,但你可以请求存储桶中文件的列表,并在脚本中自行进行字符串匹配或搜索。在PHP脚本中进行34次字符串匹配测试不应该需要那么长时间。请注意保持原意,使翻译更通俗易懂。 - thatidiotguy
我不理解你的回复 :-| - Yefb
我无法更好地解释了。请求列出存储桶中的所有文件列表,然后在脚本中自行搜索。完成。无需等待Amazon API。 - thatidiotguy
3个回答

1

速度慢是因为你在循环的每个迭代中调用 if_object_exists(),从而触发了对 AWS 的网络请求。

用户“thatidiotguy”说:

我不知道 S3 API,但你能否请求存储桶中的文件列表并在脚本中自行进行字符串匹配/搜索?在 PHP 脚本中,34 个字符串匹配测试不应该需要那么长时间。

他是正确的。

你可以在脚本开头调用 get_object_list() 一次,然后使用 PHP 的 in_array() 函数将用户照片 URL 与列表进行比较,而不是调用 if_object_exists()

你应该会看到大约百万分之一的加速。不过别引用我的话。;)


1
为什么不改变你检查的方式呢?将图像的位置/桶存储在本地数据库中,这样你就不必担心这个检查了吗?
这样可以最大限度地减少您所做的API调用数量,现在是35个,但随着时间的推移,可能会呈指数增长。而且,您不仅对每个图像进行一次调用,而且大部分情况下对每个图像进行两次调用。这是非常低效的,并且依赖于您的网络连接速度相当快。
在性能方面,将位置数据以及图像是否存在本地移动是一个更好的选择。此外,如果您提前存储结果,似乎只需要进行一次此类检查。

1

如果您想从S3读取目录类型的信息,我认为最好使用类似s3fs的工具将您的存储桶挂载为系统驱动器。 s3fs还可以配置本地缓存以加快速度(如果您正在使用EC2,则在快速临时存储上进行缓存)。

这将使您能够轻松处理常规的PHP目录操作(DirectoryIterator等)。

如果这超出了您的能力范围,至少将文件名数据存储在数据库中,并期望文件位于正确的S3位置,或者以某种方式本地缓存单个API检查的结果,以便不需要为每个类似请求进行API调用。


我找不到确切的来源,但我记得 s3fs 的开发人员曾经说过不要在生产环境中使用它。至少我们的经验表明它的性能较慢(虽然我们尝试过至少六个月了)。 - Christopher
是的,如果您不利用本地缓存目录来处理文件,性能会变得很慢。实际上,我们只是在一个遗留服务器上使用这个作为一种权宜之计,该服务器依靠多个应用服务器对一组可下载文件进行类似访问。我根本不建议采用这种架构(更喜欢以数据库为中心的方法),但这可能是OP的一个中间步骤。 - Mike Brant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接