Вы не зашли.
Главная » SQL » Выдача картинок с mysql с помощью nginx
#1. TLENS Off (14)
Moderator
2015.10.31 15:03
Есть ли такая возможность что бы не вмешивать в эту задачу php.
Перерыл интернет что то ничего не нашел на эту тему. Находил там работу nginx с mysql но совсем не понятно как реализовать данную задачу
#2. TLENS Off (14)
Moderator
2015.11.01 16:04
Уточню задачу. Нужно хранить картинки в базе так как при хранении просто на фс то сильно перегружается винт постоянно нагружен по максимуму и в следствии висит сайт.
Вот только как это реализовать что бы не давать еще нагрузку на php я хз. Хотя может и стоит это сделать через php. Хоть так хоть так изображение будет полностью выгружатся в память
#3. Gemorroj Off (107)
Administrator
2015.11.01 19:07
что-то я сомневаюсь, что нагрузка на винт большая из-за статики. много операций записи? имхо, настроить nginx с http кэшированием в большинстве случаев достаточно.
#4. TLENS Off (14)
Moderator
2015.11.07 03:03
В обьщем там кроме картинок на диске кешировались еще много файлов. И нагрузка на винт была постоянно на максимум. Переписал кеш на mysql плюс подключил memcache сайт начал летать.
Добавлено спустя   7 минут  55 секунд:
Кстати был прикол с этим хешем. Хотел удалить папку кеша >20млн. файлов(Дождался при подсчете этой цыфры потом полюнул может там и 100 лямов) и тупонул выполнив несколько раз удаление папок через nohup. В общем почему то решил ребутнуть сервер но после ребута при запуске вообще подвис так как кеш хранился в папке tmp и система начала ее чистить. Пришлось загружатся в режиме востановления и переименовывать папку))
Досихпор не могу вычистить /tmp2. Поспешил я с хранением кеша в файлах. Решил секономить время
#5. Gemorroj Off (107)
Administrator
2015.11.07 11:11
думаю, тут и mysql не лучшее решение. возможно, подошла бы какая-нибудь nosql база. например, couchdb. там можно сразу ссылку на файл в БД давать (встроенный http сервер), минуя nginx.
#6. TLENS Off (14)
Moderator
2015.11.07 20:08
Gemorroj написал:
думаю, тут и mysql не лучшее решение. возможно, подошла бы какая-нибудь nosql база. например, couchdb. там можно сразу ссылку на файл в БД давать (встроенный http сервер), минуя nginx.
Я так понял речь идет о картинках или весь кеш сайта предлагаешь хранить на этой базе?
Кеш картинок пока что не трогал. Сейчас винт нагружен примерно на 5-10%. Сейчас задача выдачи картинок стоит такова:
Получаем ссылку на оригинал картинки с базы данных далее загружаем ее через курл в память + imagecreatefromstring($data) пошаманим немного и сохраняем в файл после выдаем в браузер.
Далее этим занимается nginx смотрит есть ли картинка в кеше если есть выдает в браузер, нет перенаправляет на данный скрипт. Пока что там 240т. картинок. работает быстро. Просто тогда было очень много операций чтения записи
#7. Gemorroj Off (107)
Administrator
2015.11.08 12:12
так проблема в плохо оптимизированном php коде? ну так блин, с этого и начинал бы)
#8. TLENS Off (14)
Moderator
2015.11.08 15:03
Gemorroj написал:
так проблема в плохо оптимизированном php коде? ну так блин, с этого и начинал бы)
Не понял с чего ты взял что проблема в php. Была проблема из-за хранения данных на винте. вот функция кеша (старая)
Код:
<?php
    private function _cacheVideoSet ($data$id) {
        $fp fopen($this->_dirInfoCache $id '.txt''c+');
        if (!$fp) {
            file_put_contents($this->_errorLogFile'cacheVideoSet failed no open file['.__LINE__.']'."\n"FILE_APPEND);
            return false;  
        }
        $old_data '';
        while (!feof($fp)) {
            $old_data .= fread($fp8192);
        }
        rewind($fp);
        
        if (!$old_data) {
            $data['expire'] = $_SERVER['REQUEST_TIME'];
            fputs($fpserialize($data));
        } else {
            $old_data unserialize($old_data);
            
            if (!is_array($old_data)) {
                file_put_contents($this->_errorLogFile'cacheVideoSet unserialize ['.__LINE__.']: '$str "\n"FILE_APPEND);
                fputs($fpserialize($data));
            } else {
                
                if (@$data['title'])
                    $old_data['title'] = $data['title'];
                /*
                if ($data['description'])
                    $old_data['description'] = $data['description'];
                */
                
                if ($data['img'])
                    $old_data['img'] = $data['img'];
                if ($data['localIp']) {
                    $old_data['localIp'] = $data['localIp'];
                }
                $old_data['errno'] = @$data['errno'];
                $old_data['expire'] = $_SERVER['REQUEST_TIME'];
                if (@$data['downLinks'])
                    $old_data['downLinks'] =  $data['downLinks'];
                fputs($fpserialize($old_data));
            }   
            
        }
        
        fclose($fp);
        
    }
А вот новая
Код:
<?php
 
public function setVideosInfo($arrayData) {
        $insert "INSERT INTO `$this->_INFO_TABLE_NAME` "
                "(`id`, `title`, `description`, `duration`, `img`, `errno`, `expire`, `data`, `relative_ids`)\n";
        $values = [];
        foreach ($arrayData as $data) {
            $id "'{$data['id']}'";
            $title "'" .$this->_mysqli->real_escape_string($data['title']) . "'";
            $description "'" $this->_mysqli->real_escape_string(@$data['description']) . "'";
            $duration $data['duration'];
            $img "'" $data['img'] . "'";
            $errno = (int)@$data['errno'];
            $otherData = @$data['data']
                    ? "'".$this->_mysqli->real_escape_string(serialize($data['data']))."'"
                    "''";
            if (@$data['data']['downLinks']) 
                $expire $_SERVER['REQUEST_TIME'];
            else 
                $expire 0;
            
            $relative_ids "'" $this->_mysqli->real_escape_string(@$data['relative_ids'])."'";
            $values[] = "($id$title$description$duration$img$errno$expire$otherData$relative_ids)";
            
            
        }
        $insert .= 'VALUES 'implode (",\n"$values) . "\n"
                "ON DUPLICATE KEY UPDATE\n"
                "`title` = COALESCE(VALUES(title), description),\n"
                "`description` = COALESCE(VALUES(description), description),\n"
                "`img` = COALESCE(VALUES(img), img),\n"
                "`errno` = VALUES(errno),\n"
                "`expire` = VALUES(expire),\n"
                "`data`= COALESCE(VALUES(data), data)\n";
        if ($result $this->_mysqli->query($insert)) {
            
            //$result->close();
        } else {
            //echo $this->_mysqli->error;
            //echo $insert;
        }
        
        //echo $insert;
    }
Добавлено спустя   5 минут  24 секунды:
Просто когда все данные хранились на тупо по файлах. То увеличивалось время доступа к каждому файлу по мере их накопления.
Сейчас работает все гораздо быстрее. А если ты имеешь в виду за получение картинок то вот функция.
Код:
<?php
 
public function previewAction($m$id$type) {
        
        $path_cache '/tmp/previews/';
        
        
        $path "{$path_cache}{$m}_{$id}";
        if (!is_dir($path_cache)) {
            if (mkdir($path_cache)) {
                log(__FILE__ ': '__LINE__);
                return $this->errorAction(Response::HTTP_INTERNAL_SERVER_ERROR);
            }
            chmod($path_cache0777);
        }
        $video = new \Video\Video($m .'_'.$id);
        $video->initById();
        
        \CurlMulti::exec(true);
       
        if (@$video->getOriginalImg() == '/images/x_null.gif') {
            return $this->_getDefaultImage($type);
        }
        
        
        
        if (!$video->getOriginalImg()) {
            return $this->errorAction(Response::HTTP_NOT_FOUND);
        }
        
        $ch curl_init($video->getOriginalImg());
        $headers = array(
            'Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Language:ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4,uk;q=0.2,und;q=0.2',
            'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36',
            'Connection: close');
        
        curl_setopt($chCURLOPT_HTTPHEADER$headers);
        curl_setopt($chCURLOPT_HEADERfalse);
        curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
        curl_setopt($chCURLOPT_TIMEOUT10); 
        curl_setopt($chCURLOPT_ENCODING ,"");
        curl_setopt($chCURLOPT_FOLLOWLOCATIONtrue);
        $data curl_exec($ch);
        $info curl_getinfo($ch);
        $error curl_error($ch);
        
        if ($info['http_code'] != 200 || $error || $info['content_type'] != 'image/jpeg') {
            log(__FILE__ ': '__LINE__);
            return $this->_getDefaultImage($type);
        
        }
        
        $src_img imagecreatefromstring($data);
        
        
        $src_w imagesx($src_img);
        $src_h imagesy($src_img);
        
        // исходное соотношение
        //$src_rate = $src_w / $src_h;
        
        // необходимое соотношение
        $dst_rate 1.777777777777778;
        
        // ширина нового изображения
        $dst_w $src_w 320 $src_w 320;
        
        
        // высота результата
        $dst_h round($dst_w $dst_rate);
        
        // новая высота оригинала
        $src_h_new $src_w $dst_rate;
        
        
        // отступы вырезаемой части
        $src_indent round(($src_h $src_h_new) / 2);
        
        $src_x 0;
        $src_y $src_indent;
        
        
        
        // отступы результата
        $dst_x 0;
        $dst_y 0;
        
        
        $img_hq imagecreatetruecolor($dst_w$dst_h);
        
        // копируем прямоугольник
        imagecopyresampled($img_hq$src_img$dst_x$dst_y$src_x$src_y$dst_w$dst_h$src_w$src_h_new);
        imagedestroy($src_img);
        
        
        imagejpeg($img_hq"{$path}_HQ.jpg");
        
        
        
        
        
        
        
        // create mq image
        $mq_w 128;
        $mq_h $mq_w/$dst_rate;
        
        $img_mq imagecreatetruecolor($mq_w$mq_h);
        imagecopyresampled($img_mq$img_hq0000$mq_w$mq_h$dst_w$dst_h);
        imagejpeg($img_mq"{$path}_MQ.jpg");
        
        
        
        
        $response = new Response();
        
        switch($type) {
            case 'HQ':
                ob_start(); 
                imagejpeg($img_hq);
                $response->setContent(ob_get_clean());
                $response->headers->set('Content-Type'image_type_to_mime_type(IMAGETYPE_JPEG));
                $response->setStatusCode 200;
                break;
            case 'MQ':
                ob_start(); 
                imagejpeg($img_mq);
                $response->setContent(ob_get_clean());
                $response->setStatusCode 200;
                $response->headers->set('Content-Type'image_type_to_mime_type(IMAGETYPE_JPEG));
                break;
            default:
                return $this->errorAction(404);
        }
        
        imagedestroy($img_hq);
        imagedestroy($img_mq);
        return $response;
        
        
    }
#9. TLENS Off (14)
Moderator
2015.11.08 15:03
Можно было бы и выдавать картинку после сохранения с помощью nginx передав заголовок X-Accel-Redirect но хз че так не сделал. Может посчитал лишним.


Ну и собственно выдача в nginx
Код:
location ~* "^/(.*)/(HQ|MQ).jpg$" {
set $imageType $2;
set_escape_uri $imageName $1;
set $slash '_';
set $path $imageName$slash$imageType.jpg;
root /tmp/previews/;
if (-f /tmp/previews/$path) {
expires 3d;
rewrite (.*) /$path break;
}
rewrite (.*) /$path last;
}
#10. Gemorroj Off (107)
Administrator
2015.11.10 13:01
у тебя все файлы в 1 папке были? возможно проблема в этом
Страниц: 1 2 Все
Главная
WEB
PunBB Mod v0.6.2
0.016 s