Por qué no debería usar AWS S3 o CloudFront para entregar activos estáticos

AWS es EL chico genial de la ciudad. Cada comparación de diferentes proveedores de nube está incompleta a menos que los compare con AWS al menos una vez.

Pero S3, la solución más popular para almacenar en la nube y la que todos adoran, no siempre debe ser su elección. En este artículo, explicaré por qué.

Nota: No me grite inmediatamente sobre cómo y por qué AWS es mejor. Sé que están en la cima de la computación en la nube, y de ninguna manera estoy tratando de apuntar a ninguna de sus prácticas y servicios comerciales.

Acabo de usar CloudFront + S3 yo mismo, junto con DigitalOcean + Cloudflare también, y he establecido mis observaciones. Por favor, tomen mis pensamientos de manera constructiva, y si creen que he cometido algún error, envíenme un tweet a mehulmpt.

CloudFront + S3

CloudFront es otro servicio que se usa con frecuencia (y se recomienda) con S3 cuando intenta distribuir archivos digitalmente en todo el mundo. CloudFront es una CDN de Amazon con servidores de borde en todo el mundo. Así es como funciona:

Su usuario, digamos de la India, intenta cargar su sitio web cuyo servidor se encuentra en los EE. UU. Digamos que está usando un SPA como React o Angular. La primera página index.html se cargará desde su servidor de origen (por lo general, es una buena práctica no almacenar en caché las páginas HTML, especialmente si está utilizando aplicaciones SSR para evitar contratiempos en la caché).

Después de eso, si ha alojado sus archivos JS / CSS en CloudFront (S3), esas llamadas se realizarán a un nombre de dominio de CloudFront que se resuelve en una dirección IP de una máquina más cercana a su ubicación. En este caso, probablemente sea algún servidor de AWS ubicado en algún centro de datos en Mumbai, India.

A partir de este punto, ese servidor tiene la responsabilidad de entregar ese archivo. Pueden pasar dos cosas:

  • su archivo ya está disponible con ese servidor de Mumbai (en caché), y ese servidor le devuelve ese archivo de inmediato (acceso de caché),
  • o no tiene ese archivo y tiene que realizar un viaje a su servidor de origen (bucket S3 en este caso) para obtener ese archivo.

Pero incluso si hay una falta de caché, hay muchas posibilidades de que sea aún más rápido para un usuario en comparación con no tener CloudFront al frente.

¿Por qué? Porque cuando hay una falta de caché y el servidor de borde está tratando de llegar al servidor principal, está utilizando una línea de conexión a Internet de nivel 1 operada por Amazon, una empresa estadounidense de un billón de dólares. Es probable que tengan una conectividad a Internet y una latencia mucho mejores que las que puede ofrecer su ISP.

Además, debido a que están en la misma red global de Amazon, pueden hacer algunas optimizaciones para ahorrar más tiempo.

¡Bien! Me parece genial hasta ahora, ¿cuál es el problema? Sostenga sus caballos, lo haremos.

Compresión de activos

CloudFront le permite entregar activos comprimidos mediante GZIP. Pero incluso hay un niño más genial en el mercado: la compresión brotli. Y es compatible con casi todos los navegadores principales.

Brotli comprime aún más sus datos de transmisión. Esto significa que no solo es bueno para su billetera, sino que también es bueno para el usuario final (porque pasarán menos tiempo viendo esa pantalla de carga / en blanco).

Amazon CloudFront todavía no admite la entrega de compresión brotli. Y tampoco los culparé por esto. Esto se debe a que la compresión brotli es lenta sobre la marcha (CloudFront hace gzip sobre la marcha), por lo que aún no la han implementado.

Claro, entonces hagámoslo nosotros mismos y almacénelo en S3 y entreguemos la versión comprimida, ¿verdad? Desafortunadamente, no es tan simple y pronto nos convertiremos en un problema de arquitectura.

Una URL de activo típica se vería así: //mysite/assets/javascript/file.js

Cuando su navegador realiza una solicitud, envía un encabezado: Accept-Encoding. Este encabezado puede contener algoritmos de compresión que su navegador puede admitir, como gzip, deflate, brotli, etc. El servidor ahora tiene que actuar de manera inteligente para tener la máxima eficiencia.

  1. Si el cliente apoya brotli, siempre entregue el activo comprimido brotli.
  2. Si el cliente admite gzip, entregue siempre gzip.
  3. De lo contrario, entregue el archivo original.
  4. Además, asegúrese de que en el tipo de respuesta, esté configurada la codificación de contenido correcta para que el navegador pueda reconocer el algoritmo de compresión.

Ahora, en primer lugar, debe crear 3 variantes de cada archivo de activos:

  1. file.js
  2. file.js.br - brotli
  3. file.js.gz - gzip

Y debe entregarlos condicionalmente dependiendo de si el navegador lo admite o no. CloudFront es una CDN "tonta": simplemente asignará la URL de su solicitud al archivo de su servidor. No puede realizar ninguna transformación a menos que ... opte por otro servicio de AWS: funciones de Lambda @ edge

Es probable que todos sepamos qué es Lambda en AWS: puede ejecutar funciones en la nube sin preocuparse por la ampliación o reducción de la infraestructura subyacente. Precios por solicitud de API, con límites de tiempo, dulces. Lambda @ edge es un servicio similar pero se creó para servidores de borde (centros de datos CDN de CloudFront)

Puede configurar técnicamente un servidor Lambda para que actúe como un "intermediario" entre la solicitud realizada por su cliente y la CDN de CloudFront. Lambda puede abrir la solicitud, ver los encabezados de contenido admitidos, modificar la URL en consecuencia y reenviarla al "tonto" CloudFront, que luego recuperará el archivo de URL modificado.

Por ejemplo, si Lambda ve que el navegador envió un Accept-Encoding: br, entonces se puede usar lambda para modificar la URL de solicitud de /javascript/file.js a /javascript/file.js.br sin decirle nada al usuario. Cloudfront ahora recuperará una carga útil más pequeña y devolverá una respuesta para una codificación brotli. ¡GANAR!

Pero eso es bueno, ¿no? ¿Dónde está el problema? El problema es ... el precio.

AWS es ridículamente caro (para esta tarea)

Lo que sea que hayas hecho hasta ahora suena y se ve muy bien. Pero cuando observe lo que está sucediendo cuando comience a alcanzar números significativos, se dará cuenta de que AWS no es excelente cuando se trata de transferencia de datos. Zoom acaba de rebotar AWS por la misma razón.

Además, con la compresión de activos, ahora también tiene que pagar por las llamadas Lambda @ edge. Me di cuenta de que la implementación de Lambda @ edge realmente reducirá sus costos; de lo contrario, pagará mucho más por AWS por el tráfico.

CloudFront trabaja en los precios de transferencia de datos. No le cobra cuando recupera datos del bucket de S3, le cobra cuando un usuario recupera datos de los servidores de borde.

Límite de costo superior

En el país más caro, India, CloudFront le cobra 0,170 dólares por GB de datos transferidos. ¡Esto es enorme!

Supongamos que tiene un sitio web popular (principalmente) de la India con aproximadamente 50.000 usuarios que visitan su sitio a diario. Además, supongamos que realiza algunos cambios de diseño cada semana en su sitio (bastante común para productos de iteración rápida), por lo que debe invalidar el navegador y la caché de CloudFront.

Además, supongamos que, en promedio, un solo usuario descarga aproximadamente 10 MB del activo estático de su sitio (incluye CSS / JS / imágenes / fuentes) alojado en S3 con proxy a través de CloudFront.

Calculemos el costo:

  1. 50 mil usuarios indios
  2. 0,17 USD por GB
  3. 10 MB por usuario
  4. Cada usuario lo recupera 4 veces al mes (limpia su caché 4 veces, una vez por semana)

Costo = 50000 * 0,17 * (10/1024) * 4 = 332 USD. ¡Ese es su COSTO de solo transferencia de datos! No calculé el costo de almacenamiento de S3 ni el costo del sitio de alojamiento. (Tampoco incluí el precio de lambda porque no es mucho => $ (0.20 * (50,000 * 4)) / 1 millón = 4 centavos).

Límite de costo más bajo

En este caso, supongamos un sitio de tráfico con sede en EE. UU. Los parámetros ahora serían:

  1. 50.000 usuarios de EE. UU.
  2. 0,085 USD por GB
  3. 3 MB por usuario
  4. Cada usuario lo recupera 4 veces al mes (limpia su caché 4 veces, una vez por semana)

El costo = 50000 * 0.085 * 3 * 4/1024 = 50 USD. Eso es lo más bajo que pagará cuando use CloudFront con el tráfico mencionado (dado que todos sus 50K usuarios son solo de EE. UU.). Y recuerde, ¡ese es el costo solo para las transferencias de datos! (Sin incluir los costos del servidor para alojar su sitio web).

Alternativa

Supongamos que ahora aloja todos estos activos estáticos solo en su servidor principal: proxy inverso por NGiNX y, digamos, que se ejecuta en una instancia de DigitalOcean de $ 60.

Su transferencia de datos por mes = 50000 * (10/1024) * 4 = 1952 GB aproximadamente 2TB - DigitalOcean cubre su 1TB de transferencia por gota de forma gratuita. Y son $ 10 por 1TB a partir de entonces, por lo que serán $ 70 netos para ejecutar el servidor.

Claro, obtendrá algo de latencia ahora, porque lo está alojando usted mismo (incluso lo arreglaremos más adelante). NGiNX es un servidor web de alto rendimiento y puede confiar en que no será un cuello de botella en la entrega de sus activos estáticos.

¡Así que redujo el costo de "solo transferencia de activos" de $ 332 a $ 70 para ejecutar todo el servidor! ¿Consejo extra? Nos estábamos enfocando en ejecutar esto solo en India, así que use un servidor DigitalOcean de India. Esto significaría menos latencia.

No solo esto, sino que también puede optar por Cloudflare CDN, que es GRATIS. Cloudflare no respetará sus archivos para mantenerlos en la CDN si son demasiado grandes o si se accede con poca frecuencia. Pero estamos asumiendo un sitio increíblemente popular aquí, así que deberíamos estar bien. Si no es así, opte por cualquier otro servicio CDN, y le garantizo que será menos de $ 332 al mes.

TL; DR: si está alojando un sitio web con cantidades de tráfico medio-grandes con actualizaciones programadas regularmente, es mucho más rentable alojar los activos usted mismo y usar CDN externos (o incluso cosas como DigitalOcean CDN) en lugar de usar S3 y CloudFront (donde las tasas de tráfico de datos están por las nubes).

Conclusión

Usé esta configuración (CloudFront + AWS S3) en codedamn.com, una plataforma para que los desarrolladores aprendan y crezcan. Pronto me di cuenta de que, aunque parece elegante y puse código en las grandes ligas, Amazon, simplemente no es lo suficientemente eficiente.

¿Estas de acuerdo conmigo? ¿Qué piensas? Házmelo saber enviándome un tweet en mi Twitter o comunicándome en Instagram.

¡Paz!