Обслуживание изображений с изменением размера на лету - PullRequest
23 голосов
/ 10 февраля 2010

моя компания недавно начала испытывать проблемы с обработкой изображений для наших сайтов.

У нас есть несколько веб-сайтов (для взрослых), которые отображают такие изображения, как обложки DVD, снимки и тому подобное. У нас есть около 100 000 фильмов, и на каждый фильм у нас в среднем 30 снимков + обложки. Почти у каждого изображения есть дополнительная версия с размытием и наложением для не членов, в результате получается около 50 изображений на фильм или 5 миллионов базовых изображений. Каждое из изображений доступно в нескольких версиях, в зависимости от того, где оно размещено на странице (миниатюра, оригинал, небольшой предварительный просмотр, небольшой просмотр, небольшое изображение в верхнем списке и т. Д.), Что приводит к большему количеству изображений, чем я хотел посчитать.

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

Кто-нибудь знает о сервере обработки изображений, который может уменьшать изображения на лету, поэтому нам нужно только предоставить исходные изображения, а веб-парни могут просто запросить любой нужный размер?

Требования:

  • Очень высокая производительность (несколько тысяч пользователей в день)
  • Размытие на лету и создание наложения
  • Изменение размера «на лету» (с сохранением соотношения сторон и без него)
  • Может обрабатывать миллионы изображений
  • Должен уметь читать JPG, GIF, PNG и BMP и конвертировать между ними

Безопасность не так важна, так как, например, с помощью URL-адреса уже можно получить доступ к не размытым изображениям, и было бы неплохо, но это не требуется, и, честно говоря, я перестал заботиться (После неудачи в обсуждении моих коллег почему (для наша небольшая страница для реселлеров) плохая идея использовать http://example.com/view_image.php?filename=/data/images/01020304.jpg для отображения изображений).

Мы попробовали PHP-скрипты, чтобы сделать это, но производительность была слишком медленной для такого количества пользователей.

Заранее благодарим за любые ваши предложения.

Ответы [ 8 ]

27 голосов
/ 14 февраля 2010

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

Работает так:

  • Вы запрашиваете изображение, добавляя требуемый размер к имени файла как http://imageserver/someimage.150x120.jpg
  • если изображение существует, оно будет возвращено без какой-либо другой обработки (это главное, проверка кеша неявная)
  • если изображение не существует, обработайте 404, не найденный через .htaccess, и перенаправьте запрос в скрипт, который генерирует изображение требуемого размера
  • в сценарии укажите список допустимых размеров, чтобы избежать атак, таких как сценарии, запрашивающие каждый возможный размер для отключения вашего сервера
  • сохраните это в домене без файлов cookie, чтобы минимизировать ненужный трафик

РЕДАКТИРОВАТЬ: Я не думаю, что сам PHP сильно замедлит процесс, поскольку сценарии PHP в этом случае сводятся к минимуму: масштабирование изображения выполняется встроенной библиотекой, написанной на C. Чем бы вы ни занимались нужно использовать такую ​​библиотеку (GD или libmagick или около того), так что это неизбежно. По крайней мере, в моей системе вы полностью пропускаете накладные расходы на проверку кэша, тем самым еще больше сокращая взаимодействие с PHP. Вы можете реализовать это на своем существующем сервере, поэтому я думаю, что это решение хорошо подходит для вашего бюджета.

7 голосов
/ 10 февраля 2010

На основании

Мы попробовали PHP-скрипты, чтобы сделать это, но производительность была слишком медленной для такого количества пользователей.

Я собираюсь предположить, что вы не кэшировали результаты. Я бы рекомендовал кэшировать полученные изображения в течение дня или двух (т. Е. Сделать так, чтобы ваш скрипт проверял, был ли миниатюра уже сгенерирован, если это так, используйте его, если он не генерировал его на лету).

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

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

4 голосов
/ 13 февраля 2010

ImageCache и Точные размеры изображений решения сообщества Drupal могут сделать это, и, как и большинство решений, OSS использует библиотеки ImageMagik

Существует несколько изображений AMI для сервиса Amazons EC2 для масштабирования изображения. Он использовал Amazon S3 для хранения изображений, оригиналов и масштабов и мог передавать их в сервис Amazons CDN (Cloud Front). Проверьте на сайте EC2, что доступно

Другой вариант - Google. Документы Google теперь поддерживают все типы файлов, поэтому вы можете загружать изображения в папку документов Google и предоставлять к ней общий доступ. URL-адреса довольно длинные, например

http://lh6.ggpht.com/VMLEHAa3kSHEoRr7AchhQ6HEzHVTn1b7Mf-whpxmPlpdrRfPW216UhYdQy3pzIe4f8Q7PKXN79AD4eRqu1obC7I

Добавьте параметр = s, чтобы масштабировать изображение, круто! например для ширины 200 пикселей

http://lh6.ggpht.com/VMLEHAa3kSHEoRr7AchhQ6HEzHVTn1b7Mf-whpxmPlpdrRfPW216UhYdQy3pzIe4f8Q7PKXN79AD4eRqu1obC7I=s200

Google взимает только 5 долларов США в год за 20 ГБ. Существует полный API для загрузки документов и т. Д.

Другие ответы на SO Как лучше всего изменить размер изображения вне сервера

2 голосов
/ 14 февраля 2010

Хорошо, первая проблема в том, что изменение размера изображения на любом языке занимает немного времени. Итак, как вы поддерживаете тысячи клиентов? Мы кешируем его, поэтому вам нужно сгенерировать изображение только один раз. В следующий раз, когда кто-то запросит это изображение, проверьте, было ли оно уже сгенерировано, если оно только что вернуло это. Если у вас есть несколько серверов приложений, вам нужно будет кэшировать данные в центральной файловой системе, чтобы увеличить коэффициент попаданий в кэш и уменьшить объем необходимого вам пространства.

Для правильного кэширования необходимо использовать предсказуемое соглашение об именах, которое учитывает все возможные способы отображения изображения, например, использовать что-то вроде myimage_blurred_320x200.jpg, чтобы сохранить изображение в формате JPEG, которое было размыто и масштабировано до 300. ширина и высота 200 и т. д.

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

Вы не сможете обслуживать миллионы изображений с измененным размером любым другим способом. Это то, как карты Google и Bing делают это, они предварительно генерируют все изображения, которые им нужны для мира, в различных предустановленных экстентах, чтобы они могли обеспечить адекватную производительность и иметь возможность возвращать предварительно созданные статические изображения.

Если php слишком медленный, вам следует рассмотреть возможность использования 2D-графических библиотек из Java или .NET, поскольку они очень богаты и могут поддерживать все ваши требования. Чтобы получить представление о графическом API, вот метод в .NET, который изменяет размеры любого изображения до новой указанной ширины или высоты. Если вы опустите высоту или ширину, размер изменится, сохраняя правильное соотношение сторон. Примечание. Изображение может быть создано из JPG, GIF, PNG или BMP:

// Creates a re-sized image from the SourceFile provided that retails the same aspect ratio of the SourceImage. 
// -    If either the width or height dimensions is not provided then the resized image will use the 
//      proportion of the provided dimension to calculate the missing one.
// -    If both the width and height are provided then the resized image will have the dimensions provided 
//      with the sides of the excess portions clipped from the center of the image.
public static Image ResizeImage(Image sourceImage, int? newWidth, int? newHeight)
{
    bool doNotScale = newWidth == null || newHeight == null; ;

    if (newWidth == null)
    {
        newWidth = (int)(sourceImage.Width * ((float)newHeight / sourceImage.Height));
    }
    else if (newHeight == null)
    {
        newHeight = (int)(sourceImage.Height * ((float)newWidth) / sourceImage.Width);
    }

    var targetImage = new Bitmap(newWidth.Value, newHeight.Value);

    Rectangle srcRect;
    var desRect = new Rectangle(0, 0, newWidth.Value, newHeight.Value);

    if (doNotScale)
    {
        srcRect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height);
    }
    else
    {
        if (sourceImage.Height > sourceImage.Width)
        {
            // clip the height
            int delta = sourceImage.Height - sourceImage.Width;
            srcRect = new Rectangle(0, delta / 2, sourceImage.Width, sourceImage.Width);
        }
        else
        {
            // clip the width
            int delta = sourceImage.Width - sourceImage.Height;
            srcRect = new Rectangle(delta / 2, 0, sourceImage.Height, sourceImage.Height);
        }
    }

    using (var g = Graphics.FromImage(targetImage))
    {
        g.SmoothingMode = SmoothingMode.HighQuality;
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;

        g.DrawImage(sourceImage, desRect, srcRect, GraphicsUnit.Pixel);
    }

    return targetImage;
}
1 голос
/ 16 февраля 2016

То, что вы ищете, лучше всего соответствует Thumbor http://thumbor.readthedocs.org/en/latest/index.html, который является открытым исходным кодом, поддерживается огромной компанией (значит, он не исчезнет завтра), и поставляется с множеством приятных функций, таких как обнаружение важен для изображения при кадрировании.

Для более дешевых CDN я бы предложил объединить их с Cloudfront и хранилищем AWS или аналогичным решением с бесплатным CDN, таким как Cloudflare. Это могут быть не самые эффективные поставщики CDN, но, по крайней мере, они работают лучше, чем один сервер, а также разгрузят ваш сервер изображений по дешевке. Кроме того, это сэкономит вам тонну затрат на пропускную способность.

1 голос
/ 06 августа 2015

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

Такие сервисы, как imgix , служат прокси и CDN для операций с изображениями, таких как изменение размера и наложение оверлеев.,Управляя URL-адресом, вы можете применять различные преобразования к каждому изображению.imgix обслуживает миллиарды запросов в день.

Вы также можете самостоятельно запускать службы и размещать их за CDN.Проекты с открытым исходным кодом, такие как imageproxy , хороши для этого.Это накладывает бремя обслуживания на вашу операционную группу.

(Отказ от ответственности: я работаю на imgix.)

0 голосов
/ 09 декабря 2017

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

  1. Во встроенном CDN - вам не нужно беспокоиться о распространении изображения
  2. Изменение размера изображения на лету - доступен любой необходимый размер
  3. Нет необходимости в хранилище - вы просто храните базовый образ, и все варианты обрабатываются службой
  4. Библиотеки экосистем - вы можете просто включить JavaScript, и ваша работа будет выполнена для всех устройств и всех браузеров.

Одной из таких услуг является Gumlet . Вы также можете попробовать какую-нибудь альтернативу с открытым исходным кодом, например плагин nginx, который также может изменить размер изображения на лету.

(я работаю на Гамлета.)

0 голосов
/ 14 февраля 2010

Если каждое отдельное изображение однозначно идентифицируется по одному URL-адресу, я бы просто использовал CDN, такой как AKAMAI. Пусть ваш PHP-скрипт сделает всю работу, а AKAMAI справится с нагрузкой.

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

Редактировать : это работает, только если вы найдете CDN, который будет обслуживать этот тип контента для вас.

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