Загрузка RequestTimeout на S3 с использованием PHP - PullRequest
6 голосов
/ 20 мая 2011

У меня проблемы с загрузкой файлов в S3 с одного из наших серверов.Мы используем S3 для хранения наших резервных копий, и все наши серверы работают под управлением Ubuntu 8.04 с PHP 5.2.4 и libcurl 7.18.0.Всякий раз, когда я пытаюсь загрузить файл, Amazon возвращает ошибку RequestTimeout.Я знаю, что в нашей текущей версии libcurl есть ошибка, препятствующая загрузке более 200 МБ.По этой причине мы разбиваем наши резервные копии на более мелкие файлы.

У нас есть серверы, размещенные на Amazon EC2, и серверы, размещенные в «частных облаках» клиента (блок VMWare ESX за брандмауэром их компании).Конкретный сервер, с которым у меня возникают проблемы, размещен в частном облаке клиента.

Мы используем PHP-класс Amazon S3 из http://undesigned.org.za/2007/10/22/amazon-s3-php-class. Я пробовал файлы размером 200, 100 и 50 МБ, все сте же результаты.Для загрузки файлов мы используем следующее:

$s3 = new S3($access_key, $secret_key, false);
$success = $s3->putObjectFile($local_path, $bucket_name,
    $remote_name, S3::ACL_PRIVATE);

Я попытался установить curl_setopt($curl, CURLOPT_NOPROGRESS, false); для просмотра индикатора выполнения во время загрузки файла.В первый раз, когда я запустил его с этим параметром, он работал.Однако каждый последующий раз это не удавалось.Похоже, что файл загружается со скоростью около 3 Мбит / с в течение 5-10 секунд, а затем падает до 0. Через 20 секунд, сидя на 0, Amazon возвращает «RequestTimeout - ваше сокет-соединение с сервером не было считано или записано в течение тайм-аутапериод. Свободные соединения будут закрыты. "ошибка.

Я попытался обновить класс S3 до последней версии GitHub , но это не имело значения.Я также нашел класс Amazon S3 Stream Wrapper и попробовал использовать следующий код:

include 'gs3.php';
define('S3_KEY', 'ACCESSKEYGOESHERE');
define('S3_PRIVATE','SECRETKEYGOESHERE');
$local = fopen('/path/to/backup_id.tar.gz.0000', 'r');
$remote = fopen('s3://bucket-name/customer/backup_id.tar.gz.0000', 'w+r');

$count = 0;
while (!feof($local))
{
    $result = fwrite($remote, fread($local, (1024 * 1024)));
    if ($result === false)
    {
        fwrite(STDOUT, $count++.': Unable to write!'."\n");
    }
    else
    {
        fwrite(STDOUT, $count++.': Wrote '.$result.' bytes'."\n");
    }
}

fclose($local);
fclose($remote);

Этот код читает файл по одному МБ за раз, чтобы передать его вS3.Для файла размером 50 МБ я получаю «1: Написал 1048576 байт» 49 раз (первое число меняется каждый раз, конечно), но на последней итерации цикла я получаю сообщение об ошибке: «Примечание: fputs (): send 8192сбой в байтах с errno = 11 Ресурс временно недоступен в /path/to/http.php в строке 230 ".

Сначала я подумал, что это проблема с сетью.Мы позвонили клиенту, объяснили проблему и попросили его взглянуть на брандмауэр, чтобы узнать, не уронили ли они что-нибудь.По словам их сетевого администратора, трафик течет просто отлично.

Я не знаю, что мне делать дальше.Я выполняю резервные копии вручную и использую SCP для их передачи на другую машину и загрузки их.Это, очевидно, не идеально, и любая помощь будет принята с благодарностью.

Обновление - 23/23/2011

Я испробовал многие из вариантов ниже, но все они предоставилитот же результат.Я обнаружил, что даже попытка скопировать файл с рассматриваемого сервера на другой сервер останавливается немедленно и в конечном итоге истекает время ожидания.Однако я могу использовать scp для загрузки этого же файла с другого компьютера.Это делает меня еще более убежденным, что это проблема сети на стороне клиента, любые дальнейшие предложения будут с благодарностью.

Ответы [ 5 ]

4 голосов
/ 24 июня 2012

Эта проблема существует, потому что вы пытаетесь загрузить тот же файл снова. Пример:

$s3 = new S3('XXX','YYYY', false);
$s3->putObjectFile('file.jpg','bucket-name','file.jpg');
$s3->putObjectFile('file.jpg','bucket-name','newname-file.jpg');

Чтобы исправить это, просто скопируйте файл и дайте ему новое имя, затем загрузите его как обычно.

Пример:

$s3 = new S3('XXX','YYYY', false);
$s3->putObjectFile('file.jpg','bucket-name','file.jpg');
now rename file.jpg to newname-file.jpg
$s3->putObjectFile('newname-file.jpg','bucket-name','newname-file.jpg');
2 голосов
/ 23 октября 2013

Я решил эту проблему по-другому.Моя ошибка заключалась в том, что функция filesize () возвращает неверное значение кэшированного размера.Так что просто используйте clearstatcache ()

1 голос
/ 24 мая 2011

Существует довольно много доступных решений.У меня была именно эта проблема, но я не хотел писать код и выяснять проблему.

Изначально я искал возможность смонтировать S3 bucket на машине Linux, нашел что-то интересное:

s3fs - http://code.google.com/p/s3fs/wiki/InstallationNotes - это сработало для меня.Он использует FUSE file-system + rsync для синхронизации файлов в S3.Он хранит копию всех имен файлов в локальной системе и делает его похожим на FILE / FOLDER.

Это экономит BUNCH нашего времени + без головной боли при написании кода для передачи файлов.

Теперь, когда я пытался узнать, есть ли другие варианты, я нашел скрипт ruby, который работает в CLI и может помочь вам управлять учетной записью S3.

s3cmd - http://s3tools.org/s3cmd - это выглядит довольно ясно.

[ОБНОВЛЕНИЕ] Найден еще один инструмент CLI - s3sync

s3sync - https://forums.aws.amazon.com/thread.jspa?threadID=11975&start=0&tstart=0 - найден вСообщество Amazon AWS.

Я не вижу их обоих по-разному. Если вас не беспокоит дисковое пространство, я бы выбрал s3fs, а не s3cmd.Диск заставляет вас чувствовать себя более комфортно + вы можете видеть файлы на диске.

Надеюсь, это поможет.

1 голос
/ 23 июня 2011

Обратите внимание на AWS PHP SDK.Это библиотека AWS PHP, ранее известная как tarzan и cloudfusion.

http://aws.amazon.com/sdkforphp/

Класс S3, включенный в этот пакет, является надежным.Мы используем его для загрузки файлов размером несколько ГБ.

1 голос
/ 23 мая 2011

Я сталкивался с той же самой проблемой несколько раз.

У меня сейчас много сценариев, которые постоянно загружают файлы на S3.

Лучшее решение, которое я могу предложить, - это использоватьБиблиотеки Zend (либо потоковая оболочка, либо прямой S3 API).

http://framework.zend.com/manual/en/zend.service.amazon.s3.html

Со времени последнего выпуска инфраструктуры Zend я не видел никаких проблем с тайм-аутами.Но, если вы обнаружите, что у вас все еще есть проблемы, сработает простая настройка.

Просто откройте файл Zend / Http / Client.php и измените значение 'timeout' в массиве $ config.На момент написания этого он существовал в строке 114. До последнего выпуска я работал на 120 секундах, но теперь все идет гладко с 10-секундным таймаутом.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...