Загрузка requestTimeout в S3 с использованием PHP

#php #amazon-s3

#php #amazon-s3

Вопрос:

У меня возникли проблемы с загрузкой файлов в 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 (): ошибка отправки 8192 байт, ресурс errno = 11 временно недоступен в /path/to/http.php в строке 230».

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

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

Обновление — 23.06.2011

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

Комментарии:

1. Я был в аналогичной ситуации с PHP, в итоге приобрел оболочку командной строки FTP Linux для PHP, возможно, аналогичное решение могло бы сработать для вас. Я мало или вообще не верю в потоковый сетевой уровень PHP5, когда дело доходит до выполнения тяжелой работы, подобной вашей ситуации.

2. Вам следует попытаться изолировать проблему, чтобы узнать, какая часть вашей конфигурации вас подводит. Запустите другой экземпляр в облаке, используя похожие и разные версии PHP и т.д. чтобы посмотреть, сможете ли вы повторить сбой.

Ответ №1:

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

 $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');
  

Комментарии:

1. Есть какие-либо подсказки, почему повторная загрузка того же имени файла вызывает это? Я загружаю эскизы разных размеров, которые все поступают из одного и того же исходного файла, который я перезаписываю локально каждый раз, когда создаю новый thumb.

2. Большое вам спасибо, это решение сработало как нельзя лучше

Ответ №2:

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

Ответ №3:

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

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

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

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

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

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

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

Комментарии:

1. Я не знаю, будете ли вы когда-нибудь читать это, но это решило проблему, на устранение которой я потратил последние 2 часа. Большое спасибо. Перейти к futurama

2. Нет необходимости взламывать и редактировать Zend Http Client: Клиент будет сохраняться как статическая переменная Zend_Service_Abstract, которая позже будет использоваться Zend_Service_Amazon_S3 Zend_Service_Abstract::setHttpClient(новый Zend_Http_Client(null, array(‘timeout’ => 30))); $s3 = новый Zend_Service_Amazon_S3(‘Ключ доступа’, ‘Секретный ключ ‘, ‘регион’);

3. Вы не должны изменять Zend/Http/Client.php !

Ответ №4:

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

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

s3fs — http://code.google.com/p/s3fs/wiki/InstallationNotes — у меня это сработало. Для синхронизации файлов в S3 используется файловая система FUSE rsync. Он сохраняет копию всех имен файлов в локальной системе и делает ее похожей на ФАЙЛ / ПАПКУ.

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

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

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

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

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

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

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

Ответ №5:

Вам следует взглянуть на AWS PHP SDK. Это библиотека AWS PHP, ранее известная как tarzan и cloudfusion.

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

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