image - optimize - Sirviendo imágenes con el cambio de tamaño sobre la marcha
seo images (8)
Mi compañía recientemente comenzó a tener problemas con el manejo de imágenes para nuestros sitios web.
Tenemos varios sitios web (entretenimiento para adultos) que muestran imágenes como portadas de dvd, instantáneas y similares. Tenemos aproximadamente 100''000 películas y para cada película tenemos un promedio de 30 instantáneas + portadas. Casi todas las imágenes tienen una versión adicional con borrosidad y superposición para los que no son miembros, esto da como resultado aproximadamente 50 imágenes por película o un total de 5 millones de imágenes base. Cada una de las imágenes está disponible en varias versiones, dependiendo de dónde se coloca en la página (miniatura, original, vista previa pequeña, vista previa no tan pequeña, imagen pequeña en la lista superior, etc.) que da como resultado más imágenes que Me importaba contar
Ahora tuve la idea de usar un servidor para generar las imágenes sobre la marcha, ya que se volvió bastante torpe generar todas las diferentes imágenes para las diferentes páginas (ya que las diferentes páginas a veces incluso necesitan diferentes tamaños de imagen para básicamente la misma tarea) .
¿Alguien sabe de un servidor de procesamiento de imágenes que puede escalar imágenes al vuelo, por lo que solo necesitamos proporcionar las imágenes originales y los usuarios de la web pueden simplemente solicitar el tamaño que necesiten?
Requisitos:
- Muy alto rendimiento (varios miles de usuarios por día)
- En la marcha desenfoque y creación de superposición
- Cambiar el tamaño sobre la marcha (con y sin mantener la relación de aspecto)
- Puede manejar millones de imágenes
- Debe poder leer JPG, GIF, PNG y BMP y convertir entre ellos
La seguridad no es tan preocupante, ya que las imágenes no difuminadas ya pueden ser alcanzadas mediante la manipulación de URL y más seguridad sería agradable pero no es necesaria y francamente dejé de preocuparme (después de no poder acceder a mis compañeros de trabajo, por qué (para nuestro pequeño revendedor) página) es una mala idea usar http://example.com/view_image.php?filename=/data/images/01020304.jpg para mostrar las imágenes).
Probamos los scripts PHP para hacer esto pero el rendimiento fue demasiado lento para muchos usuarios.
Gracias de antemano por cualquier sugerencia que tenga.
Sugiero que configure un servidor web dedicado para manejar el cambio de tamaño de la imagen y servir el resultado final. He hecho algo similar, aunque en una escala mucho más pequeña. Básicamente, elimina el proceso de comprobación de la memoria caché.
Funciona así:
- solicitas la imagen añadiendo el tamaño requerido al nombre de archivo como
http://imageserver/someimage.150x120.jpg
- si la imagen existe, se devolverá sin otro procesamiento (este es el punto principal, la comprobación de caché está implícita)
- si la imagen no existe, maneje el 404 no encontrado a través de .htaccess y redireccione la solicitud al script que genera la imagen del tamaño requerido
- En el script, especifique la lista de tamaños permitidos para evitar ataques, como scripts que solicitan todos los tamaños posibles para cerrar el servidor.
- mantener esto en un dominio sin cookies para minimizar el tráfico innecesario
EDITAR: no creo que el PHP en sí mismo ralentizaría mucho el proceso, ya que las secuencias de comandos PHP en este caso se reducen al mínimo: la escala de la imagen se realiza mediante una biblioteca integrada escrita en C. Lo que sea que hagas, tendrás que usar una biblioteca como esta (GD o libmagick más o menos), eso es inevitable. Con mi sistema, al menos, omite por completo la sobrecarga de verificar el caché, lo que reduce aún más la interacción de PHP. Puede implementar esto en su servidor existente, así que supongo que es una solución adecuada para su presupuesto.
Residencia en
Probamos los scripts PHP para hacer esto pero el rendimiento fue demasiado lento para muchos usuarios.
Voy a suponer que no estabas guardando los resultados en caché. Recomiendo guardar en caché las imágenes resultantes durante un día o dos (es decir, hacer que el script se compruebe para ver si la miniatura ya se ha generado, de ser así, usarla, si no la ha generado al vuelo).
Esto mejoraría el rendimiento dramáticamente, ya que me imagino que la página principal / de inicio probablemente tenga muchos más hits que el video X aleatorio, por lo tanto, al visualizar la página principal, no es necesario crear imágenes mientras están en la memoria caché. Cuando el usuario Y ve la película X, no notarán la demora, ya que solo tiene que generar esa página.
Para el aspecto "cambiar el tamaño al vuelo", ¿qué importancia tiene para ti el ancho de banda? Me gustaría asumir que estás pasando por muchas películas que algunos kb adicionales en imágenes por solicitud no causarían demasiado daño. Si ese es el caso, podría simplemente usar imágenes más grandes y establecer el ancho y alto y dejar que el navegador haga la escala por usted.
El primer problema es que cambiar el tamaño de una imagen con cualquier idioma requiere un poco de tiempo de procesamiento. Entonces, ¿cómo ayudas a miles de clientes? Lo almacenaremos en la memoria caché para que solo tenga que generar la imagen una vez. La próxima vez que alguien solicite esa imagen, verifique si ya se ha generado, si acaba de devolverla. Si tiene varios servidores de aplicaciones, querrá guardarlos en un sistema de archivos central para aumentar la proporción de aciertos de caché y reducir la cantidad de espacio que necesitará.
Para caché correctamente, debe usar una convención de nomenclatura predecible que tenga en cuenta todas las formas diferentes en que desea que se muestre su imagen, es decir, utilice algo como myimage_blurred_320x200.jpg para guardar un jpeg borroso y redimensionado a 300 de ancho y 200 altura, etc.
Otro enfoque es situar su servidor de imágenes detrás de un servidor proxy de esa manera toda la lógica de almacenamiento en caché se realiza automáticamente para usted y sus imágenes son servidas por un servidor web rápido y nativo.
No va a poder servir millones de imágenes redimensionadas de ninguna otra manera. Así es como lo hacen los mapas de Google y Bing, pregeneran todas las imágenes que necesitan para el mundo en diferentes extensiones preestablecidas para que puedan proporcionar el rendimiento adecuado y poder devolver imágenes estáticas pregeneradas.
Si php es demasiado lento, debería considerar el uso de las bibliotecas de gráficos 2D de Java o .NET, ya que son muy ricas y pueden satisfacer todas sus necesidades. Para obtener un sabor de la API de gráficos, aquí hay un método en .NET que redimensionará cualquier imagen al nuevo ancho o alto especificado. Si omites una altura o un ancho, cambiará el tamaño manteniendo la relación de aspecto correcta. Nota La imagen puede ser creada a partir de un JPG, GIF, PNG o 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;
}
Si cada imagen diferente es única identificable por una sola URL, simplemente usaría una CDN como AKAMAI. Deje que su script PHP haga el trabajo y deje que AKAMAI maneje la carga.
Dado que este tipo de negocio generalmente no tiene problemas de presupuesto, ese sería el único lugar donde miraría.
Editar : eso funciona solo si encuentras un CDN que te sirva este tipo de contenido.
En el momento en que se formuló esta pregunta, han surgido algunas empresas para abordar este problema exacto. No es un problema que esté aislado para usted o su empresa. Muchas compañías llegan al punto en que necesitan buscar una solución más permanente para sus necesidades de procesamiento de imágenes.
Los servicios como imgix sirven como proxy y CDN para operaciones de imagen, como redimensionar y aplicar superposiciones. Al manipular la URL, puede aplicar diferentes transformaciones a cada imagen. imgix sirve miles de millones de solicitudes por día.
También puede ponerse de pie servicios por su cuenta y ponerlos detrás de un CDN. Los proyectos de código abierto como imageproxy son buenos para esto. Esto pone la carga del mantenimiento en su equipo de operaciones.
(Descargo de responsabilidad: yo trabajo para imgix.)
Lo que está buscando es mejor comparado con Thumbor http://thumbor.readthedocs.org/en/latest/index.html , que es de código abierto, respaldado por una gran empresa (significa que no desaparecerá mañana), y se envía con muchas características agradables como detectar qué es importante en una imagen cuando se cosechan.
Para CDN plus de bajo costo, sugiero combinarlo con Cloudfront y almacenamiento AWS, o una solución comparable con un CDN gratuito como Cloudflare. Puede que estos no sean los mejores proveedores de CDN, pero al menos aún funcionan mejor que un servidor y también descargan su servidor de imágenes a bajo precio. Además, le ahorrará un TON de costo de ancho de banda.
Las soluciones ImageCache y Image Exact Sizes de la comunidad Drupal pueden hacer esto, y al igual que la mayoría de las soluciones, OSS usa las bibliotecas de ImageMagik
Hay algunas imágenes AMI para el servicio Amazons EC2 para escalar las imágenes. Usó Amazon S3 para el almacenamiento de imágenes, original y escalas, y podría alimentarlos a través del servicio CDN de Amazonas (Cloud Front). Consulte en el sitio de EC2 qué hay disponible
Otra opción es Google. Los documentos de Google ahora son compatibles con todos los tipos de archivos, por lo que puede cargar las imágenes en una carpeta de documentos de Google y compartir la carpeta para el acceso público. Las URL son algo largas, por ejemplo
Agregue el parámetro = s para escalar la imagen, ¡genial! por ejemplo, para 200 píxeles de ancho
Google solo cobra USD5 / año por 20 GB. Hay una API completa para cargar documentos, etc.
Otras respuestas sobre SO ¿ Cuál es la mejor manera de cambiar el tamaño de las imágenes fuera del servidor?
Este mismo problema está siendo resuelto por los servicios de cambio de tamaño de la imagen dedicados a esta tarea. Proporcionan las siguientes características:
- En CDN integrado, no necesita preocuparse por la distribución de imágenes
- Cambiar el tamaño de la imagen sobre la marcha: cualquier tamaño necesario está disponible
- No se necesita almacenamiento: solo almacena la imagen base y todas las variantes se manejan mediante el servicio.
- Bibliotecas de ecosistemas: puede incluir Javascript y su trabajo se realiza para todos los dispositivos y todos los navegadores.
Uno de esos servicios es Gumlet . También puede probar alguna alternativa de código abierto como el complemento nginx, que también puede cambiar el tamaño de la imagen sobre la marcha.
(Yo trabajo para Gumlet.)