Con la filosofía 1RTT de Discourse, creo que podría ser el momento de reescribir el código de servicio de imágenes de avatar.
Las imágenes de avatar deben tratarse como cualquier otra carga de imagen. Se redimensionan al cargar, se almacenan y se sirven directamente desde el sistema de archivos/S3/CDN.
El método actual de Discourse utiliza un método proxy para servir imágenes de avatar. Este enfoque crea viajes de ida y vuelta HTTP innecesarios y desafíos de direcciones IP.
Aquí hay una descripción general de las solicitudes de avatar:
Se pinta el HTML inicial de Discourse.
El navegador detecta una imagen de avatar y solicita una imagen del servidor de Discourse.
El servidor de Discourse actúa como un proxy y solicita la imagen del almacén de archivos local/S3/CDN.
El servidor de Discourse recibe la imagen.
El servidor de Discourse envía la imagen al navegador.
Cada avatar personalizado tiene 1 viaje de ida y vuelta HTTP adicional y el tiempo de procesamiento del servidor relacionado. Un tema típico o una lista de temas puede tener más de 30 imágenes de avatar personalizadas. En mi sitio, eso resulta en 10 000 a 20 000 RTT adicionales y carga del servidor relacionada por día que podrían evitarse.
Además, las imágenes de avatar se llaman directamente desde el servidor. Para realizar cualquier protección a nivel de CDN, se requiere la lista blanca de la dirección IP. Esto requiere la lista blanca de las puertas de enlace en lugar de las direcciones IP del servidor. Las empresas de alojamiento realizan cambios para equilibrar el tráfico de red de forma regular. Mi dirección IP de puerta de enlace cambiará/evolucionará. El software no debería depender de la actualización de la dirección IP para que funcionen las imágenes de avatar básicas. Esto se basa en el siguiente incidente en soporte, Avatar Proxy and CDN Hot-Link Protection
Desde una perspectiva de rendimiento y simplicidad, ¿podemos tener imágenes de avatar servidas directamente desde el almacén de archivos designado de Discourse?
Esta es, de hecho, una parte muy complicada de la aplicación @LotusJeff.
Para abordar algunas de sus deficiencias, recientemente desarrollamos una forma de reducir esos viajes de ida y vuelta en nuestro hosting, pero no creo que lo hayamos documentado aquí. ¿Hay alguna documentación pública al respecto @david?
Sí, tenemos esta GlobalSetting, que puedes habilitar estableciendo la variable de entorno DISCOURSE_REDIRECT_AVATAR_REQUESTS=true
Luego, en lugar de hacer proxy, las solicitudes de avatar se servirán con una redirección 302 al almacén de archivos.
Por sí solo… no es realmente una buena idea. Significa que los navegadores tienen que hacer dos viajes completos de ida y vuelta HTTP por cada avatar. Por lo tanto, aunque podría resolver tu problema de “protección contra hotlinking”… no te recomendaría que lo habilitaras. Empeorará la experiencia de tus usuarios.
Usamos la configuración en nuestro hosting discourse.org. Pero lo complementamos con una función Lambda que se ejecuta en nuestra CDN Cloudfront. Detecta el 302 y realiza el proxy por sí misma. Esencialmente: movemos el proxy de nuestros servidores de aplicaciones a la CDN.
En cuanto a la pregunta más general de “podemos cambiar los avatares para que enlacen directamente al activo”. Es complicado porque las URL de los avatares están incrustadas en todas las publicaciones históricas (por ejemplo, citas). Las URL dinámicas /user-avatar/ nos permiten mantener esas publicaciones funcionando cuando un usuario cambia su avatar. Me temo que no tenemos planes de cambiar ese sistema.
Si hay una manera fácil y de bajo riesgo de hacer que el proxy existente funcione para tu caso de uso (por ejemplo, agregar una GlobalSetting que inserte una cabecera HTTP específica en cualquier solicitud de proxy de avatar), entonces podríamos considerar aceptar una PR para el cambio.
Ninguna de las opciones mencionadas anteriormente es factible o preferida en mi entorno actual. Me encantaría ayudar a resolver esta parte convoluta de la aplicación, pero soy muy nuevo en este stack tecnológico.
La única asistencia que puedo ofrecer ahora es usando mis viejos habilidades de BA y gestión de desarrollo. Entonces, en el espíritu de sentir que estoy ayudando, estos son mis pensamientos.
Cuando veo algún enigma técnico, primero considero las posibles suposiciones que harían que una solución sea más difícil.
Una suposición es guardar una imagen de avatar actualizada como un nuevo nombre de archivo. La persona solo tiene un avatar. No guardamos un registro de los nombres de avatar. Sugeriría que cuando una persona actualiza su imagen de avatar, se guarde usando el mismo nombre de archivo que el avatar existente. Esto es básicamente lo que hace el enlace /user-avatar/. En lugar de tener una solución alternativa, realiza esta lógica durante la creación/actualización del avatar. Esto resolvería las preocupaciones de las publicaciones históricas para futuras publicaciones horneadas.
¿Es esto un cambio de golpe? No, este cambio podría implementarse en meses, mejorando lentamente el rendimiento del sitio. Mis equipos de desarrollo siempre tenían una lista de código oportunista para cada bloque de código. Queríamos hacer estas mejoras, pero no eran críticas para hacerlas individualmente. Cuando el código se abría para desarrollo por alguna otra razón, el desarrollador también hacía cambios oportunistas. Esto minimizaba nuestras pruebas y errores al reducir las veces que el código se abría y actualizaba.
Dividiría este proyecto en las siguientes fases:
Actualizar la lógica de guardado de la imagen de avatar para reemplazar cualquier actualización de imagen usando el nombre de archivo actual.
Reemplazar todos los usos de las imágenes de avatar con una función estándar que utilice el sistema preferido de almacenamiento/distribución de archivos de discourse. Esto podría implementarse en meses, moviéndose lentamente a la nueva lógica de presentación de la imagen de avatar.
Una vez completadas las dos primeras, proporcionar a la comunidad los pasos y fragmentos de código para cambiar y rehechar las imágenes de avatar históricas en HTML horneado a su sistema de archivos preferido. Esto dependería de la elección de cada propietario del sitio de discourse para implementarlo. (Estas instrucciones y fragmentos de código serían útiles para hacer cambios en HTML sin procesar)
Estoy seguro de que has considerado todo esto. También sé que corregir el código más antiguo nunca suele ser una prioridad.
Si hay algo en lo que pueda ayudar en este esfuerzo, por favor avísame.
PD. Aprecio la oferta de un PR para la configuración del encabezado global. Dejaré que investigue un poco más y te siga con requisitos más definidos. Gracias por tu ayuda.
Desafortunadamente, si el archivo es mutable, significaría que ya no podríamos habilitar el almacenamiento en caché infinito del recurso en la CDN y los navegadores de los usuarios finales.
Existen estrategias para hacer que algo así funcione sin perjudicar demasiado el rendimiento… por ejemplo, la directiva stale-while-revalidate. Pero eso conlleva sus propios costos e implicaciones en la experiencia del usuario.