Los avatares tardan mucho en cargar después de moverse a R2 compatible con S3

Hola,

Acabo de migrar a R2 y todo salió perfectamente. Todas las imágenes tienen el enlace de la URL del CDN de S3. Sin embargo, noté un problema: los avatares tardan mucho en cargar. En promedio, tarda entre 3 y 4 segundos, ya sea que haga clic en el avatar de un usuario o que lo observe dentro de una publicación. ¿Es esto esperado?

Mmm, sospecho que podría deberse a uno de tres problemas diferentes, pero el más probable para mí es el redimensionamiento en tiempo real.

1. Redimensionamiento de avatares en tiempo real

Cuando migraste tus subidas a R2, se movieron las imágenes originales; sin embargo, Discourse utiliza muchos tamaños diferentes de avatares (por ejemplo, 45px para los mensajes, 120px para la tarjeta de usuario).

Si esos tamaños optimizados específicos no se migraron perfectamente o aún no se han generado, Discourse tiene que generarlos de forma sincrónica en el momento en que el usuario hace clic en ellos:

  1. Discourse descarga el avatar original desde R2 al servidor local.
  2. Lo redimensiona utilizando ImageMagick.
  3. Sube el nuevo tamaño de vuelta a R2.
  4. Redirige el navegador a la nueva URL, y este proceso tarda entre 3 y 4 segundos.

Para verificar: actualiza forzosamente la página (hard-refresh). Si el avatar tarda 3-4 segundos la primera vez, pero carga instantáneamente la segunda vez, esto es exactamente lo que está ocurriendo.

Para solucionarlo: esto se solucionará naturalmente a medida que los usuarios naveguen y se generen los tamaños. Pero puedes solucionarlo al instante forzando al servidor a pregenerar todos los avatares en segundo plano accediendo por SSH a tu servidor y ejecutando:

./launcher enter app
rake avatars:refresh

2. El tiempo de espera de 3 segundos de IPv6

Si los avatares tardan 3-4 segundos cada vez, incluso después de múltiples actualizaciones, es probable que estén alcanzando un tiempo de espera de red.

Los puntos finales de la API de Cloudflare R2 son de doble pila (dual-stack), es decir, utilizan tanto IPv4 como IPv6. Si tu gota del servidor tiene una dirección IPv6 asignada, pero la puerta de enlace IPv6 del anfitrión no está enrutada correctamente, la conexión interna de Ruby al cubo de R2 intentará usar IPv6 primero, se colgará durante 3 segundos (este es el tiempo de espera TCP predeterminado de Linux), fallará y luego se conectará con éxito de forma instantánea usando IPv4.

Para verificar: accede por SSH al servidor y ejecuta:

curl -I -6 https://cloudflare.com

Si se cuelga durante unos segundos y falla, el IPv6 del servidor está roto, lo que hace que cada verificación interna de la API de S3 sufra un retraso de 3 segundos.

Para solucionarlo: necesitarás corregir el enrutamiento IPv6 en el panel de control de tu anfitrión o quizás incluso desactivar IPv6 en la gota del servidor por completo.

3. Retardos de Gravatar

Si tu sitio está configurado para verificar las actualizaciones de Gravatar, es posible que esté enviando pings a los servidores externos de Gravatar antes de renderizar el avatar. Si el servidor tiene una conexión saliente lenta (también relacionada a menudo con DNS o IPv6), es probable que bloquee la renderización del avatar.

Para verificar: ejecuta esto en tu servidor:
curl -I -6 https://gravatar.com
Si se cuelga durante 3 segundos, el IPv6 está roto (ver arriba).

Solución relacionada con Gravatar: en la configuración de Discourse, ve a descargar automáticamente gravatars, desactívala temporalmente y comprueba si eso lo soluciona. No creo que este sea el problema, pero si lo fuera, puedes dejar la configuración desactivada, o corregir el enrutamiento IPv6 como se indica en el punto 2 anterior, o quizás cambiar el resolvedor DNS.

Gracias por su rápida respuesta. Creo que ya había intentado antes el comando ‘rake avatars:refresh’, pero no estoy completamente seguro.

Lo que solía funcionar para mí para ver que el avatar se abriera inmediatamente era hacer clic en él por primera vez; la segunda vez, se abría instantáneamente. Pero eso probablemente se deba a la caché. Además, acabo de probar su segundo consejo y devuelve un «HTTP/2 301», junto con varias otras líneas. Lo mismo ocurre con el consejo 3. Ejecutaré avatars:refresh nuevamente en unos días, ya que necesité restaurar una instantánea. ¡Gracias de nuevo!

Gravatar

server: nginx
date: Mon, 22 Jun 2026 19:29:00 GMT
content-type: text/html; charset=utf-8
content-length: 0
content-language: en
expires: Wed, 11 Jan 1984 05:00:00 GMT
cache-control: no-cache, must-revalidate, max-age=0
x-redirect-by: Gravatar
location: https://en.gravatar.com/
alt-svc: h3=":443"; ma=86400
strict-transport-security: max-age=31536000; includeSubdomains; preload

CF

HTTP/2 301
date: Mon, 22 Jun 2026 19:27:00 GMT
content-type: text/html
content-length: 167
location: https://www.cloudflare.com/
cache-control: max-age=3600
expires: Mon, 22 Jun 2026 20:26:59 GMT
set-cookie: __cf_bm=eBP2aJ7Eg30nHPuvMMNxxKrgNtcNwKs0WDgnYyONeus-1782156420-1.0.1.1-sXpW27iuhGDF615cOfwNFybH4IMxgvZy3uA_3X_o..402T_3KSgT7CSymipL5RjdpGe3raWEqsVxQFFLPKRoDjfoT7B.0rqyDt.osbkOF98; path=/; expires=Mon, 22-Jun-26 19:57:00 GMT; domain=.cloudflare.com; HttpOnly; Secure; SameSite=None
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=QfYqSekEDPJHC2k%2BMjHN0cGjz172tmUWe2GSR8EgwNLh3TGjFYkQ0vwPxlzY1NcBcKFOMaAi4FlgjqjhETOOtHf%2BH9KdQSvqN3OME2Uh1i4nHIw%2Fy1qkvSpf4jxDchM7CaDW80tJkjBV4OqF"}],"group":"cf-nel","max_age":604800}
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
strict-transport-security: max-age=15780000; includeSubDomains
server: cloudflare
cf-ray: a0fda5d8ecd6b26d-LAX
alt-svc: h3=":443"; ma=86400

sí, dada tu respuesta, estoy casi seguro de que se trata del problema #1 porque los resultados del comando curl para cloudflare y gravatar parecen ser los esperados. Prueba con rake avatars:refresh cuando te sea conveniente y avísame si funciona.

Hola Lilly, sigo teniendo el mismo problema. Incluso después de ejecutar rake avatars:refresh. El problema persiste incluso en /latest. Probé limpiando la caché desde mi navegador y desde Cloudflare, pero sin éxito todavía. ¿Quizás necesito esperar un poco? Lo estoy probando en un foro con 4500 usuarios.

no borres más el caché de tu navegador o de Cloudflare: cuando ejecutas rake avatars:refresh para tantos usuarios, esto no ocurre de forma instantánea. En su lugar, se envían miles de trabajos a Sidekiq para que se procesen en segundo plano, lo que puede tardar varias horas dependiendo de la CPU de tu servidor. Lo siento, debería haber mencionado Sidekiq y que puede tardar un poco dependiendo de cuántos usuarios haya.

Ve a your-forum.com/sidekiq/queues y observa la cola. Espera a que se vacíe por completo. Una vez que Sidekiq termine, todos los tamaños deberían estar en tu bucket de R2 de forma permanente, y creo que la carga de tus avatares volverá a la velocidad normal.

Ok, creo que está pasando algo más. No tengo nada en mis colas. Pero si hago clic en el avatar de cualquier usuario, esto aparece en ‘tail -f log/production.log’: Sent file /var/www/discourse/tmp/avatar_proxy/3689d91eb5e1013beef831c585b5e62edeeecbd6.jpeg (0.2ms)

¡Vaya, vale! Esto probablemente sea la prueba definitiva y apunta a un problema diferente.

avatar_proxy en los registros suele significar que Discourse se niega a servir la imagen directamente desde el CDN R2 de Cloudflare. En su lugar, Discourse intercepta agresivamente la solicitud, descarga la imagen desde R2 a la carpeta /tmp del servidor local y luego usa Ruby para servirla al navegador. Así que creo que esto está evitando por completo el CDN y explica el retraso de 3 segundos: sospecho que el servidor está obteniendo y cargando el archivo manualmente en cada solicitud :grimacing:

Discourse utiliza avatar_proxy en algunos escenarios muy específicos y, por lo general, es una configuración de privacidad o seguridad que obliga al servidor a enmascarar la URL externa.

Verifica estas configuraciones en Administración > Configuración del sitio:

Busca external system avatars url (URL de avatares de sistemas externos). Si hay algo en ese cuadro (como /letter_avatar_proxy/v4/...), bórralo para que quede vacío. Eso debería evitar que Discourse proxye los avatares predeterminados de letras. También vale la pena verificar uploaded avatars allowed groups (grupos permitidos para avatares cargados) y asegurarse de que diga TL_0.

Tal vez verifiquen también DISCOURSE_S3_CDN_URL para asegurarse de que sea correcta, sin una barra al final ni errores tipográficos.

Reasignar avatares personalizados:
Parece probable que tu base de datos aún contenga las URL crudas del bucket R2 en lugar de tu nueva URL de CDN; como no coinciden, tu foro probablemente las está proxyando por razones de seguridad.

Verifica en la consola de Rails para ver exactamente con qué está luchando Discourse:

./launcher enter app
rails c

Elige un nombre de usuario con un avatar de carga lenta.

u = User.find_by_username("el_nombre_de_usuario_seleccionado")
u.user_avatar.custom_upload.url

Si la salida devuelve una URL cruda del bucket, tus reasignaciones anteriores no capturaron todo (quizás se haya pasado por alto un subdominio o un esquema).

Para solucionarlo, inicia sesión por SSH en tu servidor, vuelve a tu contenedor nuevamente (no a rails) (./launcher enter app) y ejecuta la herramienta de reasignación (de nuevo, jaja) para cambiar la URL cruda por tu URL de CDN:

discourse remap "https://<tu-url-cruda-de-cloudflare>.r2.cloudflarestorage.com" "https://cdn.tu-dominio.com"

Luego ejecútala una segunda vez usando // en lugar de https:// por si acaso.

Por cierto, solo por curiosidad, ¿qué servicio de hosting estás utilizando? Tengo una configuración general similar a la tuya y aún no he experimentado este problema. Así que también estoy interesado en tu configuración y quiero intentar reproducirlo de alguna manera.

La URL que obtengo muestra la URL de la CDN de S3 y puedo abrir la imagen en el navegador.

Por ahora dejaré de lado S3, ya que realmente no lo necesito en este momento.

Además, llevo mucho tiempo usando Advinservers.

Gracias por tu ayuda, lo aprecio mucho.