2015-08-27 3 views
2

Я работаю над сайтом, который использует ImageMagick для генерации изображений. Сайт будет получать сотни запросов каждую минуту, и с помощью ImageMagick это приведет к сбою сайта.Оптимизация одновременных запросов ImageMagick с использованием redis/php-resque

Итак, мы реализовали Redis и Php-resque, чтобы генерировать ImageMagick в фоновом режиме на отдельном сервере, чтобы он не разбивал наш главный. Проблема в том, что для получения изображений все еще требуется очень много времени. Пользователь может ожидать до 2-3 минут для запроса изображения, потому что сервер так занят обработкой этих изображений.

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

Ниже приведен пример сценария ImageMagick, который мы используем:

convert -size 600x400 xc:none \(".$path."assets/images/bases/base_image_69509021433289153_8_0.png -fill rgb\(255,15,127\) -colorize 100% \) -composite \(".$path."assets/images/bases/eye_image_60444011438514404_8_0.png -fill rgb\(15,107,255\) -colorize 100% \) -composite \(".$path."assets/images/markings/marking_clan_8_marking_10_1433289499.png -fill rgb\(255,79,79\) -colorize 100% \) -composite \(".$path."assets/images/bases/shading_image_893252771433289153_8_0.png -fill rgb\(135,159,255\) -colorize 100% \) -compose Multiply -composite \(".$path."assets/images/highlight_image_629750231433289153_8_0.png -fill rgb\(27,35,36\) -colorize 100% \) -compose Overlay -composite \(".$path."assets/images/lineart_image_433715161433289153_8_0.png -fill rgb\(0,0,0\) -colorize 100% \) -compose Over -composite ".$path."assets/generated/queue/tempt_preview_27992_userid_0_".$filename."_file.png 

Моя теория состоит в том, что причина, это занимает довольно много времени из-за процесса окрашивания изображений. Есть ли способ полностью оптимизировать этот процесс?

Любой, кто имеет опыт работы с тяжелыми грузами процессов imagemagick или может увидеть некоторые из самых простых способов оптимизации наших запросов, я был бы очень благодарен.

Спасибо :)

+0

Каковы размеры пикселей «активы/изображения/базы/base_image_69509021433289153_8_0.png'? И размер файла? Каковы спецификации процессора и оперативной памяти сервера? Сколько базовых изображений у вас есть вообще? –

ответ

0

Очередь обрабатывается по одному за раз? Вы пытались выполнить параллельные задания, которые будут работать параллельно, поэтому вы будете работать сразу несколько элементов, если это так?

+0

Hi; Я пробовал несколько сотрудников (я делал тесты с 1,3, 5), но на сервере, на котором мы находимся, мы нашли его лучше, просто имея 1 рабочего (ребята из сервера сказали нам, что это связано с тем, что сервер лучше обрабатывает запросы или что-то). У нас был еще один сервер, где 5 сотрудников работали чуть лучше, чем 1, но время ожидания было по-прежнему очень высоким. – Patchesoft

+0

Вы пробовали очередь рабочего? Как Beanstalk? или RabittMQ? –

2

Ваша команда на самом деле сводится к следующему:

convert -size 600x400 xc:none         \ 
    \(1.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    \(2.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    \(3.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    \(4.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    \(5.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    \(6.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    result.png 

Мои мысли таковы:

Пункт 1:

Первый -composite на пустой холст кажется бессмысленным - предположительно 1.png представляет собой PNG 600x400 с прозрачностью, поэтому ваша первая линия может избежать операции компоновки и сэкономить 16% времени обработки, изменив ее на:

convert -background none 1.png -fill ... -colorize 100% \ 
    \(2.png .. 
    \(3.png ... 

Пункт 2

Я поставил эквивалент вашей команды в петлю и сделал 100 итераций и она занимает 15 секунд. Затем я изменил все ваши чтения PNG-файлов на файлы MPC - или файлы Magix Pixel Cache. Это сократило время обработки до чуть менее 10 секунд, то есть на 33%. Magic Pixel Cache - это всего лишь предварительно распакованный, предварительно декодированный файл, который можно читать непосредственно в память без какого-либо усилия процессора. Вы можете предварительно создать их, когда ваш каталог изменится и сохранит их вместе с файлами PNG. Для того, чтобы сделать один вы

convert image.png image.mpc 

и вы получите из image.mpc и image.cache.Тогда вы просто изменить код, чтобы выглядеть следующим образом:

convert -size 600x400 xc:none         \ 
    \(1.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    \(2.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    \(3.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    \(4.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    \(5.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    \(6.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \ 
    result.png 

Пункта 3

К сожалению, вы не ответили еще на мои вопросы, но если каталог ваших активов не слишком большой, вы могли бы поставить что (или эквиваленты MPC выше) на RAM-диск при запуске системы.

Пункт 4

Вы определенно должны работать параллельно - что даст наибольшие выгоды всех. Это очень просто с GNU Parallel - example here.

Если вы используете REDIS, это на самом деле проще, чем это. Всего LPUSH ваших MIME кодированных изображений в список Redis, как это:

#!/usr/bin/perl 
################################################################################ 
# generator.pl <number of images> <image size in bytes> 
# Mark Setchell 
# Base64 encodes and sends "images" of specified size to REDIS 
################################################################################ 
use strict; 
use warnings FATAL => 'all'; 
use Redis; 
use MIME::Base64; 
use Time::HiRes qw(time); 

my $Debug=0; # set to 1 for debug messages 

my $nargs = $#ARGV + 1; 
if ($nargs != 2) { 
    print "Usage: generator.pl <number of images> <image size in bytes>\n"; 
    exit 1; 
} 

my $nimages=$ARGV[0]; 
my $imsize=$ARGV[1]; 

# Our "image" 
my $image="x"x$imsize; 

printf "DEBUG($$): images: $nimages, size: $imsize\n" if $Debug; 

# Connection to REDIS 
my $redis = Redis->new; 
my $start=time; 

for(my $i=0;$i<$nimages;$i++){ 
    my $encoded=encode_base64($image,''); 
    $redis->rpush('images'=>$encoded); 
    print "DEBUG($$): Sending image $i\n" if $Debug; 
} 
my $elapsed=time-$start; 
printf "DEBUG($$): Sent $nimages images of $imsize bytes in %.3f seconds, %d images/s\n",$elapsed,int($nimages/$elapsed); 

, а затем запустить несколько рабочих, которые все сидят там делают BLPOPs рабочих мест, чтобы сделать

#!/usr/bin/perl 
################################################################################ 
# worker.pl 
# Mark Setchell 
# Reads "images" from REDIS and uudecodes them as fast as possible 
################################################################################ 
use strict; 
use warnings FATAL => 'all'; 
use Redis; 
use MIME::Base64; 
use Time::HiRes qw(time); 

my $Debug=0; # set to 1 for debug messages 
my $timeout=1; # number of seconds to wait for an image 
my $i=0; 

# Connection to REDIS 
my $redis = Redis->new; 

my $start=time; 

while(1){ 
    #my $encoded=encode_base64($image,''); 
    my (undef,$encoded)=$redis->blpop('images',$timeout); 
    last if !defined $encoded; 
    my $image=decode_base64($encoded); 
    my $l=length($image); 
    $i++; 
    print "DEBUG($$): Received image:$i, $l bytes\n" if $Debug; 
} 

my $elapsed=time-$start-$timeout; # since we waited that long for the last one 
printf "DEBUG($$): Received $i images in %.3f seconds, %d images/s\n",$elapsed,int($i/$elapsed); 

Если я запустить один процесс Парогенератора выше, и заставить его генерировать 100 000 изображений по 200 кбайт каждый, и читать их с 4 рабочими процессами на моей разумной спецификации iMac, это занимает 59 секунд, или около 1700 изображений/с могут проходить через REDIS.

 Смежные вопросы

  • Нет связанных вопросов^_^