【发布时间】:2019-10-17 14:20:08
【问题描述】:
我有一个架构相当简单的 webapp:
- 面向公众的负载平衡器的 HAproxy
- 运行 Apache 的网络服务器
- 运行 AWS S3 SDK 的内部 API 服务器
- MySQL 数据库服务器
我的网络应用程序有一个重大问题。基本上,我的 Web 应用程序利用内部 API 服务器来执行一些与文档相关的离散功能(因此是 AWS S3)。 API 在正常情况下工作正常,但是如果出现错误(例如文件不存在或权限不足),则 PHP 代码会挂起。我已经通过我的网络应用程序和 cURL 对此进行了测试,我可以轻松地复制该问题。
基本使用模式:
- Webserver 通过 IP 地址向 API Server 发起 POST cURL 请求
- 出于安全目的,API 服务器验证请求的 Web 服务器是否属于 IP 白名单(在我在 AWS VPC 中使用的安全组之上,以同样的方式限制流量)
- API 服务器然后向 AWS S3 发起请求
- API 服务器属于一个 IAM 角色,该角色有权访问自定义 S3 策略,该策略授予它对 S3 的必要权限
总结一下:
- 如果文件名和权限正常,一切正常
- 如果文件名错误或权限不足,请求会挂起 5-10 分钟(有效地使我的 Web 服务器无法使用,直到请求超时)
这令人担忧有两个原因:
- S3 政策已经相当严格,但我需要在不久的将来进一步锁定它
- 我不希望我的整个网站在出现问题时就死掉,我希望它能够优雅地处理异常
我尝试通过我的网络应用程序和 cURL 使用 API,但出现了相同的行为(即挂起 5-10 分钟)。
require '/var/www/html/private/aws/aws-autoloader.php';
use Aws\Credentials\CredentialProvider;
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
$s3 = S3Client::factory(['version' => 'latest','region' => 'ap-southeast-2',]);
try
{
$s3->deleteObject(array(
'Bucket' => $path,
'Key' => $in_filename
));
$numResult=1;
}
catch (S3Exception $e)
{
echo $e->getMessage() . "\n";
$numResult=0;
}
echo $numResult;
如果出现问题,我希望输出一个 0 字符,这将提示我进一步调查和/或我可以改进代码以将异常发送到系统日志或类似文件。
(顺便说一句,我将 $path 和 $in_filename 值设置得很好,将它们排除在代码之外)。
【问题讨论】:
-
它是版本化的还是非版本化的 s3 存储桶?如果你尝试捕捉一个通用的\Exception,你会捕捉到任何东西吗?这应该删除多个文件还是只删除一个文件?
-
这是一个非版本化的 S3 存储桶。如果权限或文件名(尤其是在 COPY 的情况下)错误,则在执行 COPY 或 PUT 等任务的其他 PHP API 上会发生相同类型的挂起。一次只删除一个文件。
-
如果我将 catch 行更改为 Exception 而不是 S3Exception 没有区别 - 同样的问题仍然存在。
-
S3 库是否有任何超时设置?十分钟的挂起很奇怪 - curl 默认值应该比这低得多。
-
即使我将超时设置为一个较低的值(比如说 5 秒),那也意味着我的网络服务器将超时(http504)来自其他用户的任何请求,直到 API 请求完成。仍然不理想。
标签: php curl exception amazon-s3