Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Отдача изображений при высокой нагрузке сайта


Автор: Promosoft 31.8.2010, 23:49
Делаю сайт с преобладанием изображений (галереи и т.д.), в будущем с высокой посещаемостью (нагрузкой).
Применяется Apache mod_rewrite, строка выглядет гораздо страшнее, с каталогами, упрощённый вариант:
Код
RewriteRule ^image/(.*)$ uploads/image.php?img=$1 [L]


image.php тоже большой и страшный. Кусок, отвечающий за вывод изображения:
Код
$image_info = getimagesize( "/image/myfoto.gif" );
header('Content-Type: '.$image_info["mime"]);
readfile($thumb);
exit;


Вопрос:
При высоких нагрузках могут ли возникнуть проблемы или лучше сразу отдавать статику без php срипта, т.е. ограничиться mod_rewrite'ом через .htaccess?

Автор: gta4kv 1.9.2010, 00:10
Что в вашем понятие высокая нагрузка?

Автор: skyboy 1.9.2010, 00:23
Цитата(Promosoft @  31.8.2010,  22:49 Найти цитируемый пост)
или лучше сразу отдавать статику без php срипта, т.е. ограничиться mod_rewrite'ом через .htaccess? 

не понимаю, как вторая часть предложения связана с первой.

Автор: Promosoft 1.9.2010, 08:08
Цитата(gta4kv @  1.9.2010,  00:10 Найти цитируемый пост)
Что в вашем понятие высокая нагрузка?
Минимум 100к хостов и показов > 1кк. Поэтому я и интересуюсь, стоит ли волноваться или это моя фантазия.

Цитата(skyboy @  1.9.2010,  00:23 Найти цитируемый пост)
не понимаю, как вторая часть предложения связана с первой.
Возможно криво написал, смысл был понятен, давайте не будем писать лишнее.

Пожалуйста, старайтесь писать по теме.

Добавлено через 6 минут и 16 секунд
skyboy,
за  отдачу статического контента, отвечает Apache (если он установлен). .htaccess - это апач.
Если вы не поняли меня, значит или вы издеваетесь или действительно не понимаете.

Автор: skyboy 1.9.2010, 09:36
Цитата(Promosoft @  1.9.2010,  07:08 Найти цитируемый пост)
Если вы не поняли меня, значит или вы издеваетесь или действительно не понимаете. 

ну, да, Капитан Очевидность, я "действительно не понимаю". Не понимаю, нафига без отдачи контента РНР скриптом использовать mod_rwrite для статики.
Поищи статьи о серверной оптимизации. Куча их. На том же хабрахабре. Люди уходят от Апача на nginx, ибо там можно выдержать гораздо б̀ольшее количество соединений. Переносят статику вообще на отдельный сервер. Используют CDN. Вылизывают отправляемые заголовки Expires, Last-Modified, механизм ETag. 
А у тебя Apache, mod_rewrite и php скрипт, который при каждом запросе дергает файловую систему и даже не формирует заголовки со временем модификации.

Автор: gta4kv 1.9.2010, 12:01
Цитата(Promosoft @ 1.9.2010,  08:08)
Цитата(gta4kv @  1.9.2010,  00:10 Найти цитируемый пост)
Что в вашем понятие высокая нагрузка?
Минимум 100к хостов и показов > 1кк. Поэтому я и интересуюсь, стоит ли волноваться или это моя фантазия.

Фантазия это:
Цитата

Минимум 100к хостов и показов > 1кк.

Автор: lexxmix 1.9.2010, 12:39
Цитата
При высоких нагрузках могут ли возникнуть проблемы или лучше сразу отдавать статику без php срипта,

Лучше сразу отдавать статику без php скрипта.

Цитата
ограничиться mod_rewrite'ом через .htaccess?

Нет смотри в сторону  XCache, APC, eAccelerator из оперативы отдача быстрей чем от диска.

http://php.net/manual/en/function.readfile.php

Везде использовать правильные header.

Оптимизируй код для генерации статики 1 раз в кэш на определенное время.

Автор: Mishelik 23.6.2013, 19:17
а томкат с нативом чем плох?

Автор: Sanchezzz 23.6.2013, 20:39
Если и оптимизировать то зарание начиная от хранилищя файлов.
Самая большая ошибка это хранить файлы в одной папке.

После 10к файлов в одной папке линикса уже начинаются малозаметные тормоза по выбору файла оп римому линку.
Максимальный порог 200к файлов но какие тормоза.
А подключить раздел в случаи если размер заканчивается просто не возможно.

Файлы лучше хранить в ирархии папок 5 уровней в полне хватает для этой цели. Пример:
/storage/e1/bc/32/имя файла
/storage/e1/bc/32/x3/a1/имя файла
итд.

Лучше ngnix использовать в голом виде или в связке с апачем, я предпочитаю в голом smile
Отдавать лучше всего всегда статику. в вашем пример уж точно, или как-то кешировать.

ТС Суть image мне не ясна вижу только вывод, сама суть для чего он нужен мне не ясно.
Саму функциональность опишите если не секрет.

Можно конфиг настроить в ngnix что бы URl с картинкой сохранял в кеш как статику.

Кешировать картинки XCache, APC, eAccelerator очень сомнительная польза, мы в место статичной отдачи  заниемся опять выводом через PHP...


Тот-же ngnix можно кеш хранить в оперативки или любом другом хранилище, если я не ошибаюсь. 
Можно даже определенные типы URL кешить например ресайз оригинала из PHP в кеш NGNIX дальше сервер отдает статику из кеша.
Плюсом такой системы мы не храним 100ресайзов вечно на диске, храним только то что интересует пользователей.
Временная папка и не актуальный кеш сам чистится. Храним только оригинал без комплекта тумбочек место больше для файлов, меньше затрат=)

Кстати Манифест(HTML5) кто не будь использовал для кеша

UPD...
Mishelik Ну ты некропостер, я и за тебя потратил время на бесполезный ответ, который может быть и не нужен.






Автор: IgorIV 24.6.2013, 07:25
Sanchezzz,  кто знает может и не зря отвечал ... smile 
Mishelik, в следующий раз сразу извиняйся, что вытащил некропост. А то топик вверху вводит в заблуждение, что тема свежая.

Автор: krundetz 24.6.2013, 09:20
Цитата(Mishelik @  23.6.2013,  19:17 Найти цитируемый пост)
а томкат с нативом чем плох? 

тем что ветка про PHP, а ты некропостер. В следующий раз за такое минус влеплю.

Цитата(Sanchezzz @  23.6.2013,  20:39 Найти цитируемый пост)
Mishelik Ну ты некропостер, я и за тебя потратил время на бесполезный ответ, который может быть и не нужен.

Мне пригодится. насчет ограничения количества файлов, есть сслыки на иследования?

Автор: Sanchezzz 24.6.2013, 11:28
Все из личного опыта по хранению большого количества файлов.
Поначалу этого даже не заметишь. 




У меня уже давно для этих целей класс по хранению файлов реализован...
Код

<?php

if(!defined('DS')) define('DS' , '/'); //DIRECTORY_SEPARATOR

/**
 * Класс хранилище файлов
 *
 * @Using:
 *
 * $file = '/tmp/abcde.jpg';
 * $newfile = Storage::make('photo')->move_file($file, 'photo', 'jpg');
 */

class Storage {

    protected static $instances = array();

    protected $config;

    /**
     * Возвращает объект Storage
     *
     * @static
     * @param null $type
     * @return Storage
     */
    public static function make($type = null)
    {
        if ($type === null){
            $type = 'default';
        }

        if (!isset(Storage::$instances[$type])){
            $storage = new Storage;
            $storage->config = config::get('storage');

            Storage::$instances[$type] = $storage;
        }

        return Storage::$instances[$type];
    }

    public function __construct(){}

    // Создать уникальный путь к файлу
    private function unique_filepath($base_path, $nesting_level, $ext){
        $filename = md5(uniqid()).'.'.trim($ext,'.');

        // Подготовить путь к файлу
        $filedir = $base_path;

        for ($i = 0; $i < $nesting_level; $i++){
            if (!file_exists($filedir)){
                throw new CException('Directory not exists: :filedir', array(':filedir' => $filedir));
            }

            if (!is_dir($filedir)){
                throw new CException('Not directory: :filedir', array(':filedir' => $filedir));
            }

            if (!is_writable($filedir)){
                throw new CException('Not writable directory: :filedir', array(':filedir' => $filedir));
            }

            $filedir .= substr($filename, $i * 2, 2).'/';

            @mkdir($filedir);
        }

        $filepath = $filedir.$filename;

        // Проверить существование файла
        if (file_exists($filepath)){
            $filepath = $this->unique_filepath($base_path, $nesting_level, $ext);
        }

        return $filepath;
    }


    // Переместить файл в хранилище
    public function move_file($path, $type, $ext){
        $type = isset($this->config['types'][$type]) ? $type : 'file';
        $ext = $ext ? $ext : 'file';

        // Проверить существование файла
        if (!$path OR !@is_file($path)){
            return false; // file not found
        }

        // Получить данные из конфига
        $storage_base = $this->config['storage_base'].DS
            .$this->config['types'][$type]['files_dir'].DS;

        $nesting_level = $this->config['types'][$type]['nesting_level'];

        // Создать уникальный путь к файлу
        $storage_filepath = $this->unique_filepath($storage_base, $nesting_level, $ext);

        // Скопировать файл
        @copy($path, $storage_filepath);
        @chmod($storage_filepath, 0666);

        // Удалить старый файл
        @unlink($path);

        return $storage_filepath;
    }

    // Создать пустой файл с уникальным именем в хранилище
    public function create_empty_file($type, $ext){
        $type = isset($this->config['types'][$type]) ? $type : 'file';
        $ext = $ext ? $ext : 'file';

        // Получить данные из конфига
        $storage_base = $this->config['storage_base'].DS
            .$this->config['types'][$type]['files_dir'].DS;

        $nesting_level = $this->config['types'][$type]['nesting_level'];

        // Создать уникальный путь к файлу
        $storage_filepath = $this->unique_filepath($storage_base, $nesting_level, $ext);

        // Создать пустой файл
        $f = fopen($storage_filepath, "w");
        fclose($f);
        @chmod($storage_filepath, 0666);

        return $storage_filepath;
    }

    // Получить относительный путь из абсолютного
    public function get_relative_path($path){
        return str_replace($this->config['storage_base'], '', $path);
    }

    public function get_absolute_path($relative_path){
        return $this->config['storage_base'].$relative_path;
    }
}


// Кофиг в виде массива
Код

return array(
       'storage'=> array(
        'storage_base' =>$commonConfigDir ."/../../", 
        
        'types'        => array(
            'photo'  => array(
                'files_dir'     => 'photo',
                'nesting_level' => 5,
            ),
            'banner' => array(
                'files_dir'     => 'banner',
                'nesting_level' => 5,
            ),
            'video'  => array(
                'files_dir'     => 'video',
                'nesting_level' => 5,
            ),
        ),
    ),
)








Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)