En idealista damos mucho valor al contenido de nuestros anuncios. No nos importa tanto el ser quienes más inmuebles publiquemos -eso acaba llegando-; pero lo que sí nos quita el sueño es no hacer perder el tiempo a nuestros usuarios con anuncios que no cumplan unos criterios mínimos para resultarles útiles.
Algo a lo que damos muchísimo valor para conseguir esto último, es a que los anuncios tengan tanto contenido multimedia como sea posible. Intentamos conseguir que para el usuario, navegar por nuestros anuncios sea lo más parecido posible a visitar el piso; y para eso necesitamos poder mostrar tantas fotos, vídeos, planos o visitas virtuales como podamos.
¿Pero qué nos supone a nosotros intentar conseguir esta experiencia de usuario? Pues tener que procesar y servir una cantidad cada vez mayor de contenidos multimedia a diario. Para que os hagáis una idea:
- Almacenamos en nuestros sistemas más de 100 millones de multimedias entre fotos, videos, visitas, etc. Estamos hablando de unos 80TB de datos.
- Todos los días se suben a la web más de 350K multimedias que tenemos que obtener, procesar y almacenar.
- Recibimos diariamente 150 millones de peticiones HTTP a multimedias. Esto equivale a decir que servimos más de 5TB de datos diarios sólo en fotos (más de 1PB anual)
Tradicionalmente siempre hemos gestionado este tipo de contenido en máquinas e infraestructura propias. ¿Pero qué ha terminado ocurriendo? Que según hemos ido creciendo, cada vez se han hecho más patentes una serie de problemas:
- Se nos hacía difícil escalar la infraestructura a la velocidad que nos requería nuestro propio crecimiento. Y no sólo hablamos de picos de tráfico: todos los cambios en la web orientados a dar más peso al contenido multimedia de los anuncios nos suponían un quebradero de cabeza.
- Cada vez invertíamos más tiempo en tareas de mantenimiento y gestión de estos sistemas. Cada pocos años teníamos que hacer una renovación de la infraestructura de almacenamiento que soportara nuestras nuevas necesidades, con el coste en hardware y migración de datos que ello suponía.
Cada vez se hacía más patente que, en este contexto, no compensaba que nosotros nos hiciésemos cargo de toda la infraestructura. Albergar la plataforma en la nube nos iba a permitir centrarnos exclusivamente en el desarrollo de aquellos servicios que tuvieran que ver con los multimedias. Al final nos decidimos a usar Amazon AWS.
¿Cómo es la solución que hemos adoptado?
La solución que hemos acabado implementando sobre AWS es la siguiente:
Los servicios de AWS en los que nos hemos basado son éstos:
- Amazon S3: El servicio de almacenamiento por excelencia de Amazon. Un disco duro en la nube. Es donde almacenamos todo nuestro contenido multimedia.
- AWS Lambda: Se trata de un servicio de computación orientado a eventos. ¿Qué quiere decir esto? Simple: que nosotros le vamos a decir a Amazon que ejecute una pieza de código (que nosotros hayamos cargado previamente) cada vez que ocurra alguno de los eventos que AWS Lambda tiene definidos. Amazon nos va a cobrar por el tiempo de computación utilizado en ejecutar nuestro código.
¿Para qué lo utilizamos? Para procesar los multimedias que suben nuestros usuarios. Cada vez que un cliente sube un multimedia a S3 (evento), se ejecuta el procesado del mismo. En el caso de las fotos generamos el corte que nosotros realmente vamos a almacenar. En el caso de los videos, la función lambda se encarga de llamar a Elastic Transcoder.
- Amazon Elastic Transcoder: Se trata de un servicio de transcodificación de multimedias. Como hemos comentado arriba, lo utilizamos para procesar los videos que suben nuestros clientes. Se encarga de generar los formatos y calidades de vídeos que necesitamos, los snapshots de los mismos….
- Amazon SQS: Es el nombre que recibe el servicio de colas de Amazon. Cada vez que un multimedia queda procesado, encolamos un mensaje que lo indique en alguna de nuestras colas. Tenemos una serie de servicios que se dedican a consumir los mensajes de estas colas y persisten el nuevo estado de los multimedias en nuestros sistemas.
- Amazon SNS: Servicio de notificaciones de Amazon (Simple Notification Service). Básicamente es el servicio de mensajería (pub-sub) de Amazon. En nuestro caso lo necesitamos para escuchar el topic en el que el Elastic Transcoder publica que ha terminado de procesar un video y para el servicio de monitorización y alertas que utilizamos gracias a CloudWatch.
- Amazon EC2: El servicio de computación en la nube clásico de Amazon. Básicamente nos da una capacidad de cómputo determinada para ejecutar cualquier proceso o servicio propio que queramos. La gracia está en que nos abstrae de cualquier tipo de escalado o del hardware que haya por debajo. ¿Que tenemos un pico? Amazon se encargará de levantarnos tantas instancias de EC2 como necesitemos para que no perdamos capacidad de servicio (eso sí, pasaremos por caja). Cada vez que veis una foto en idealista, las máquinas que os las sirven son instancias EC2.
- AWS Elastic Load Balancing: Se trata de un balanceador de carga entre instancias de EC2. Permite equilibrar cargas entre las mismas, así como asegurar la alta disponibilidad de los servicios que proveen. Si por un casual un día perdemos un servidor de fotos en EC2, el Elastic Balancer hará que todas las peticiones al mismo sean redirigidas a alguna otra instancia.
- Amazon CloudFront: Es el nombre que tiene el servicio CDN de Amazon. Pedir a los servidores de multimedias una y otra vez la misma foto termina cargando innecesariamente los mismos. Un CDN es una capa intermedia que hace de alguna forma de caché de estas peticiones; sirviendo él mismo los multimedias que se pidan de manera recurrente y libreando de ese trabajo a otros servicios.
- Amazon CloudWatch: Es el gran hermano. El servicio que nos permite monitorizar todos los componentes anteriores. Podemos ver cargas, número de peticiones, generar alertas si algún componente falla…
¿Cómo procesamos los multimedias?
Todo empieza con la subida manual desde la web, las apps o desde los procesos de importación masiva. Cuando finaliza la subida y el fichero queda almacenado en el bucket de imágenes/vídeos pendientes, se genera un evento que es recogido por la función Lambda correspondiente, la cuál se encargará de realizar todo el trabajo de procesado sobre el multimedia.
En el caso de las imágenes utilizamos sharp: una librería de procesado de imágenes escrita en Node.js que wrappea libvips, y que nos permite crear los thumbnails que posteriormente serviremos en las diferentes páginas de idealista. Estas nuevas imágenes son almacenadas en el bucket maestro al que acceden los thumbnails servers (más adelante hablaremos sobre ellos).
La imagen original la movemos al bucket de originales -si ha ido bien el procesado-, o al de errores en caso de fallo.
Por último, encolamos en SQS la información de la imagen procesada. ¿Por qué? Porque estos mensajes son recogidos posteriormente por nuestros microservicios de multimedias , que se encargarán de actualizar en nuestra base de datos el estado final junto con determinados parámetros que tenemos una vez la imágen ha sido procesada.
Para el caso de los vídeos, en el procesado hacemos uso de la herramienta AWS Elastic Transcoder que nos permite de manera simple automatizar las tareas de procesado y codificación. Una de las ventajas principales de usar Elastic Transcoder es que no tenemos que preocuparnos de dar soporte a toda la cantidad de formatos de vídeo/codecs existentes.
La función Lambda encargada del procesamiento de vídeos envía a Elastic Transcoder la ruta del fichero en S3 y los parámetros para generar los formatos que necesitamos. Una vez procesado el video, en la configuración de procesado de Elastic Transcoder indicamos el topic de SNS al que, una vez tratado el fichero original, se debe enviar el resultado. La configuración de este topic de SNS incluye la generación de un mensaje que se encolará en SQS y que de manera similar a la imagen contendrá la información para actualizar el estado en base de datos.
Una consideración común -tanto en fotos como en vídeos-, que nos ha permitido ganar en performance ha sido la generación de las rutas a los multimedias en S3. Tal y como Amazon explica en este artículo, cuando el número de elementos con el que trabajar es grande hay que intentar distribuir el número de peticiones por el máximo de particiones de S3 que podamos. Poner nombres fijos o secuenciales (un timestamp por ejemplo) en las rutas hacen que la carga no se distribuya correctamente, lo cual puede acabar notándose. Para evitar estos problemas, las rutas a todos nuestros multimedias llevan tres niveles de claves hexadecimales de dos caracteres. La ruta de una foto ficticia sería algo parecido a https://s3.nuestrodominio.com/nom_bucket/ac/2f/1c/mifoto.jpg.
Una vez procesados, ¿cómo los servimos?
En este post os contábamos la forma de servir los thumbnails antes de la migración a AWS. Las decisiones detrás de la arquitectura que planteamos entonces son las mismas que nos han guiado ahora; sólo que esta vez están implementadas en la nube.
Las fotos, videos… que veis en nuestra web los sirven un conjunto de instancias EC2 que nosotros llamamos Thumbnail Servers. Son los encargados, partiendo de una petición, de seleccionar la imagen de origen en el bucket de S3 y escalarla al vuelo para entregar el tamaño deseado al usuario.
Como es de esperar, hay momentos de más y menos tráfico que repercuten directamente sobre la carga de trabajo de estas máquinas. Una de las ventajas de tenerlas en AWS, es que podemos ayudarnos de los algoritmos de autoescalado para adaptarnos a esos cambios. Gracias a ellos conseguimos crear instancias que se auto-instalan y entran en servicio de manera automática. Incluso podemos ajustar más los costes al utilizar instancias de subasta (spot instances). Evidentemente, cuando el nivel de peticiones decrece, automáticamente se retiran del balanceador y se apagan. Se acabó el tener que levantar máquinas a mano como locos cada vez que tenemos una subida fuerte de tráfico.
De la misma manera que es importante esta funcionalidad de añadir/quitar instancias, también lo es la de elegir el tipo de instancia correcta. Entre el amplio catálogo de servidores que nos deja elegir AWS, en nuestro caso hemos elegido instancias c3.xlarge, las cuales nos proporcionan un buen equilibrio de recursos para nuestras necesidades. Confiamos en un pool fijo que se autoescala con instancias del mismo tipo; pero en vez de utilizar las instancias habituales, utilizamos spot instances para ajustar mejor los costes.
Pero no sólo nos fiamos del autoescalado de EC2 para tener todo bajo control. Por encima de todos los Thumbnail Servers tenemos un Elastic Load Balancer que distribuye las cargas en cada uno de ellos. De esta forma evitamos tener instancias al límite mientras otras prácticamente no tienen trabajo y nos aseguramos que estas funcionan correctamente, en caso contrario, no se las pasa tráfico y son retiradas.
Y por si todo esto fuera poco, delante de todos los Thumbnail Servers tenemos a CloudFront cacheando y sirviendo él mismo muchas de las peticiones redundantes a contenido multimedia que soportamos a diario.
Esta capa de CDN nos evita volver a procesar cerca de un 80% de las peticiones -con el consiguiente ahorro de recursos y reducción del tiempo de entrega de contenido-. Como comentábamos al principio, entregamos más de 1PB de contenido al año.
Y con todo esto cubrimos el ciclo de vida de cualquiera de las fotos o vídeos que pululan por idealista. Para que no se pierda ninguno. Para que podamos verlos todos. Para que podamos verlos siempre :-)


Muy buen arrículo. Gracias por hacerlo público.
Hola chicos
Muy buen articulo, gracias por hacerlo público.
Sin embargo, adolece de determinadas circunstancias, que, me permito comentar como experto en plataformas de computación y muy muy fan de AWS.
Montar la infraestructura en AWS es lo «cool» ahora. Y reconozco que está muy bien, pero os habéis metido en una trampa de la cual os va a costar salir. AWS esta muy bien, repito, pero ya no podréis salir de ahi. Aunque sea mucho mas caro que cualquier otra solución del mercado.
Creo que para un proyecto complejo como el vuestro es un error basarlo todo en Amazon. Usar tantas piezas es un error garrafal, porque en el fondo solo estaís haciendo dos cosas, upload+recorte y download de las fotos.
Si el sistema previo era complejo me parece bien la labor de reingeniería, pero, en mi modo de ver, suspendéis en la implementación y en la herramienta.
Insisto, soy fan de AWS y lo uso «con cabeza» en mi organización, cediendo solamente aquellas partes individuales que puedo mover a otro sitio algún día, sin necesidad de desmontar o hacer un proyecto a la inversa.
Lo bueno de AWS es que es como las drogas o el buen sexo, siempre quieres mas, y acabaréis metiendoos aún mas profundamente en su sistema, que es fantástico, pero del cual ya no podréis salir.
Ya veréis la factura de CloudFront que risa.
Mucha suerte chicos, esto no deja de ser un comentario como otros, pero, cuidado con las modas.
Gracias por compartir este tipo de cosas. Necesito montar algo más sencillo con AWS y vuestro post me ha servido de gran utilidad. No estaba al tanto de AWS Lambda, seguramente lo acabe utilizando
Muchas gracias por el artículo, es realmente muy interesante :-)
Desde un punto de visto económico, se ha analizado a 3-5 años el ahorro que supone realizar todo en AWS en lugar de sobre plataforma propia?
Según el articulo y según lo que entiendo sobre el tema, ya no es el ahorro si no la complejidad que supone seguir escalando a esos niveles.
americar tiene bastante de razon, aunque no creo que sea el fin del mundo, siempre puedes sustituir (sin hacer mucha reingenieria) EC2, Load Balancer, Cloudfront basandote en NGINX para crear un CDN inhouse, API gateway/management y reducir bastante la complejidad y la factura. Aqui el problema que veo es que han tirado por la automatizacion y reducir de alguna manera, tener que manejar todo ellos, pero hoy en dia hay muchas opciones. Usar las soluciones nativas de el proveedor cloud es un fallo, si mañana quieres coger Azure or GCP, estas jodido