У меня есть веб-приложение, архитектура которого довольно проста:
- HAproxy для балансировщиков нагрузки для общественных мест
- Веб-сервер под управлением Apache
- Внутренний API-сервер под управлением AWS S3 SDK
- Сервер базы данных MySQL
У моего веб-приложения есть серьезная проблема. По сути, мое веб-приложение использует внутренний сервер API для выполнения отдельных функций, связанных с документами (отсюда AWS S3). API работает нормально при нормальных условиях, однако, если есть ошибка (например, файл не существует или недостаточно прав), то код PHP зависает. Я протестировал это в своем веб-приложении, а также через cURL, и я могу легко воспроизвести проблему.
Базовая схема использования:
- Веб-сервер инициирует запрос POST cURL к серверу API через IP-адрес
- API-сервер проверяет, что запрашиваемый веб-сервер относится к белому списку IP-адресов в целях безопасности (помимо групп безопасности, которые я использую в AWS VPC для аналогичного ограничения трафика)
- Сервер API затем инициирует запрос к AWS S3
- Сервер API принадлежит роли IAM, у которой есть доступ к пользовательской политике S3, которая предоставляет ему необходимые разрешения для S3
Подведем итог:
- Если имя файла и права в порядке, все работает нормально
- Если имя файла неверное или недостаточно прав, запрос зависает на 5-10 минут (фактически, мой веб-сервер становится недоступным до истечения времени ожидания запроса)
Это беспокоит по двум причинам:
- Политика S3 уже довольно ограничительна, но в ближайшем будущем мне нужно еще немного ее заблокировать
- Я не хочу, чтобы весь мой сайт умер, просто если что-то пойдет не так, я хочу, чтобы он корректно обрабатывал исключения
Я пытался использовать API из своего веб-приложения и через cURL, и происходит то же самое поведение (то есть зависание на 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, оставив их вне кода).