La actualización en tiempo real de temas se congela bajo alta actividad

Nota: No estoy seguro de si esto es un error en Discourse. He intentado recopilar la evidencia necesaria y, hasta ahora, no he encontrado nada que señale nuestra infraestructura o configuración. Nuestra configuración es lo más estándar posible en Tappara.co.

Fenómeno observado:

  • Los temas de discusión rápida tipo chat dejan de actualizarse automáticamente. Tras un retraso de 30 a 180 segundos, la actualización suele reanudarse, mostrando los mensajes publicados durante la congelación.

Lo que sabemos hasta ahora

  • No observamos esto en la temporada anterior; el último partido se jugó en marzo.
  • Ejecutamos la rama estable y realizamos la última actualización mayor en agosto.
  • El problema se reportó inmediatamente en los primeros partidos de exhibición, con tráfico/actividad moderado.
  • Esto afecta a iOS y a Chrome en Android, pero es mucho menos frecuente en Chromebook.
    • Mientras escribo esto, veo congelaciones en mi teléfono Android, mientras que la discusión fluye como se espera en mi Chromebook. Dos dispositivos diferentes en la misma red.
  • La experiencia varía según el usuario/cliente. Diferentes usuarios reportan las congelaciones en momentos distintos. En general, registramos aproximadamente 300 mensajes en unos 30 minutos y los usuarios reportaron docenas de congelaciones. En su mayoría, las congelaciones parecen correlacionarse con eventos del juego (goles, penalizaciones).

Cosas que he intentado descartar

  • CloudFlare: jugamos un partido sin la caché de CF y el problema persistió.
  • Sobrecarga de CPU: el uso de CPU está bien dentro de los límites, generalmente oscilando entre el 20% y el 30%.
  • Agotamiento del disco: la E/S del disco parece estar bien dentro de los límites. Tenemos SSD MaxIOPS de UpCloud.

Otra información

  • Tuve el inspector de Chrome ejecutándose durante el partido y se registraron algunos errores 429, pero para mí no correlacionaron con las congelaciones.
  • Los usuarios finales no reciben notificaciones sobre los errores 429 (ralentización) ni sobre la carga extrema. La actualización simplemente se congela y luego se reanuda. ¿Ha cambiado el limitador de tasa recientemente? Tengo la impresión de que los límites de tasa deberían activar un aviso en la interfaz de usuario.

Un problema realmente molesto que afecta gravemente los chats de juego minuto a minuto. Hemos estado ejecutando estos durante años y nunca había visto esto antes.

Bueno, no es un error, sino una característica :sweat_smile:.

Cuando tus web workers comienzan a verse abrumados por las solicitudes, introducimos retrasos en la conexión persistente que actualiza automáticamente el tema cuando llegan nuevos mensajes.

Si ves esto y el uso de CPU es bajo según lo reportado, por favor aumenta el número de workers de unicornio y esto debería solucionar el problema.

Ya tenemos 11 Unicorns en un VPS de 6 núcleos. Como se mencionó, esto nunca ocurrió durante la temporada anterior, la más reciente en marzo. Ahora ocurre incluso con tráfico moderado. Además, esto sucede mucho más en dispositivos móviles, especialmente en Chrome para Android, que en escritorio.

También hemos logrado agotar nuestra CPU anteriormente (en el plazo límite de transferencias de jugadores).

Me perdí un partido monitoreando y ajustando el servidor. Duplicamos los parámetros web.ratelimited, pero eso no resolvió el problema.

Inspector detecta varios errores 429:

1. URL de la solicitud:

https://tappara.co/message-bus/3ed86765a67f4c31ba4053a0352ecaf5/poll

2. Método de la solicitud:

POST

3. Código de estado:

429

El próximo partido es mañana, así que puedo probar con los Unicorns. ¿Hasta qué punto podemos subir? ¿Ha cambiado esto con la última actualización importante?

Edición:

Revisé las estadísticas y, hasta ahora, nuestra actividad ha sido menor que la que tuvimos en primavera (páginas vistas, usuarios). El número de publicaciones por chat de partido es idéntico (alrededor de 900-1000 por 3 horas).

Por una razón desconocida, actualmente no podemos atender a la misma audiencia que teníamos en marzo.

Estoy trabajando en el análisis de este problema durante las próximas dos semanas; tomará tiempo mejorarlo.

¡Genial! ¿Podrías confirmar si ha habido algún cambio o regresión reciente (en los últimos 6 meses) que haya causado esto?

Mientras tanto, creo que aumentaré la energía de los unicornios para el partido de esta noche y veré qué pasa. Si podemos apoyar de alguna manera, solo avísame.

@falco El número de unicornios definitivamente no es la clave. Los aumenté a 15 para el juego de esta noche. El tema del juego fue tranquilo, solo 700 mensajes, pero se observó congelamiento constante. La carga de la CPU fue leve, entre 5-25%.

Cuanto más investigo esto, más probable parece que sea un problema y una regresión, pero mis habilidades no son lo suficientemente buenas para identificar dónde.

Creo que hay un error en el cliente que hace que deje de actualizarse básicamente después de recibir un error. Sospecho que esto te está ocurriendo porque tus usuarios están alcanzando el límite de solicitudes.

Esta semana investigaré cómo hacer que el cliente sea más robusto. Como mencioné antes, este es un código delicado y llevará tiempo.

Bien. Mientras tanto, probaré si desactivar el limitador global sería una solución alternativa. Lo sabremos el miércoles.

Depurar este problema me llevó a reflexionar sobre la experiencia de usuario (UX) de las discusiones casi en tiempo real en general. Muchas comunidades se ocupan de eventos de la vida real, lo que naturalmente «empuja» la conversación hacia un estilo de chat rápido. Puede ser el mercado de valores, el lanzamiento de un producto importante o un juego (eSports o físico)… lo que sea.

Pero en este tipo de cultura de discusión tipo chat, la calidad de los mensajes varía mucho. Por otro lado, los mensajes tienden naturalmente a ocurrir exactamente al mismo tiempo. Imaginemos que hay un gran partido de hockey en curso y alguien anota un gol.

  • Una gran parte de los mensajes son solo reacciones emocionales, vítores o lamentos.
    • ¡Goooool!!! Sí, bebé
  • Algunos son informativos:
    • Crosby anota, 1-0 para los Pens
  • Una pequeña minoría se toma el esfuerzo de incluir algún análisis:
    • Crosby anota un gol en ruptura, tras un descuido en la presión por parte de los Caps, pero pareció mucho una jugada de fuera de juego. El entrenador de los Caps debería impugnarla.

Ahora, dado que Discourse es una plataforma rápida (casi en tiempo real), esto significa que incluso cuando todo funciona sin problemas, recibirás varias docenas de mensajes prácticamente en el mismo instante. Para el lector, especialmente para quien no está viendo el juego pero lo sigue en el tema de chat, esto plantea un desafío de UX: es difícil identificar esos mensajes informativos en medio de los vítores y lamentos. En los chats de juegos de nuestro foro, a menudo nos preguntan ¿Cuál es el marcador?, ya que los participantes que ven el juego olvidan publicar lo obvio, o la información se pierde en la avalancha de mensajes.

No sé cómo funcionaría esto en la vida real, pero sería interesante probar si los administradores podrían establecer el ritmo de la discusión. Por ejemplo, un mensaje por segundo. Todos los mensajes se pondrían en cola, pero se publicarían en el sitio a un ritmo definido. Si un gol genera 20 mensajes de reacción, no aparecerían en el tema al mismo tiempo, sino durante una ventana de 20 segundos. ¿Sería más fácil seguir el hilo y captar la información relevante?

Por supuesto, esto podría generar otros problemas: si el ritmo de los nuevos mensajes supera constantemente el ritmo de publicación, se formaría una cola cada vez más larga y el chat empezaría a ir por detrás de la realidad.

No sé si habéis entendido la idea, y ni siquiera yo estoy seguro de que sea buena. La conclusión es que la UX del chat en tiempo real es un tema interesante de discusión y podría tener potencial para un desarrollo futuro. Entiendo que el enfoque principal de Discourse no es crear una plataforma de chat: para eso ya existen otros programas. Pero estos chats ocurren de forma natural.

Me gusta esa idea, pero necesitaría algún tipo de sombra inversa para que las personas siempre vean sus propias publicaciones de inmediato. Si no lo hacen, podrían publicar dos o incluso tres veces, pensando que el foro no funciona.

Acabo de fusionar esto:

https://review.discourse.org/t/perf-backoff-background-requests-when-overloaded-10888/16227

Esto asegura que no se sature un servidor si 1000 personas están viendo un tema y se están publicando mensajes.

El cliente ahora se comporta de manera mucho más limpia en estos casos.

Anticipando la pregunta de @ljpp, aún no he decidido si hacer un backport; esto implica cambios en la API y es una modificación bastante grande. Si hacemos el backport… probablemente pasen unas pocas semanas. Necesito observar esto en producción bajo carga y, como tenemos mucho margen en nuestro alojamiento y ocurren muy pocos eventos como este, tardará un tiempo en presentarse.

Trucos de la mente Jedi :wink:

  • Probaremos si desactivar el limitador de velocidad es una solución viable.
  • Si lo es: Supongo que la próxima versión estable no está muy lejos.
  • Si no lo es, revisaremos el canal Beta. Tendremos que verificar que nuestras personalizaciones de la interfaz no se vean afectadas por la actualización.

¿Conocéis alguna otra comunidad que tenga discusiones similares tipo chat y que funcione en ramas edge?

Esperamos una para finales de año… así que no esperes que llegue muy pronto. ¡Sin embargo, lanzaremos otra versión beta esta semana!

Todos nuestros servicios de alojamiento funcionan con la versión beta… así que sí, pero tenemos una gran capacidad.

Entiendo la lógica detrás de por qué esto podría no ser un candidato para un backport. Acabo de desactivar nuestro ratelimiter y mañana es el siguiente juego, así que tendremos una idea aproximada de si sirve como una solución viable para las instancias que no están dispuestas a entrar en beta.

Definitivamente estamos considerando lanzar la rama beta durante los próximos meses. Sin embargo, también hay otras preocupaciones: @rizka señaló que la traducción al FI se está quedando atrás (aunque podría trabajar en ello más adelante esta semana).

@sam

Lamentablemente, desactivar el limitador de velocidad no ayudó en absoluto. Fue un partido aburrido y 83 usuarios publicaron solo 580 mensajes. Se reportaron varios congelamientos durante el juego.

¿Hay algún hack o solución alternativa potencial que podamos probar mientras esperamos la actualización a una versión edge?

Las ‘congelaciones’ son un error del cliente; simplemente no reaccionó correctamente ante las condiciones de error. Incluso un solo error de límite de velocidad y estás fuera de la versión estable.

No se me ocurre ninguna solución alternativa salvo actualizar a la versión beta (lanzaremos una nueva mañana).

Uno de nuestros miembros orientados al desarrollo propuso ajustar la siguiente variable. ¿Qué opinas? ¿Ves esto como una posible solución temporal?

DISCOURSE_REJECT_MESSAGE_BUS_QUEUE_SECONDS: 0.2

Probamos el truco:

DISCOURSE_REJECT_MESSAGE_BUS_QUEUE_SECONDS: 0.2

Esto redujo significativamente la cantidad de ralentizaciones observadas, pero no resolvió el problema. La carga de la CPU aumentó, oscilando alrededor del 55% en momentos de eventos importantes en el juego.

Recientemente se han realizado cambios para ayudar con los “congelamientos”; el cliente se detendrá y esperará si el servidor está sobrecargado.

Sin embargo, la solución definitiva podría ser obtener un servidor más grande y ejecutar más trabajadores de Unicorn. Consulta el script discourse-setup para nuestras recomendaciones sobre la relación entre la capacidad del servidor y el número de trabajadores.

Lo dudo… el problema bajo una alta carga de respuestas es que, antes del nuevo diseño, podíamos generar una avalancha que activaba los límites de velocidad debido a max_reqs_per_ip_per_10_seconds y similares. Se necesitarían recursos enormes para manejar esa carga.

Piénsalo:

  • 30 usuarios publican una respuesta en 10 segundos.
  • 100 personas están viendo el tema.
  • El servidor debe poder manejar 3000 solicitudes GET para solicitar un solo mensaje a la vez.
  • Si CUALQUIERA de estas solicitudes falla por cualquier motivo, la interfaz se congelaría y parecería rota.

El nuevo diseño resuelve este problema de manera muy limpia: las solicitudes se reducen de forma ordenada, se agrupan si hay un retraso, la interfaz no se congela, etc.

No veo cómo el diseño anterior podría escalar a 100 usuarios concurrentes y 30 respuestas en 10 segundos.

Sí veo que el diseño actual revisado funciona bien con 1000 usuarios concurrentes viendo un tema con 30 respuestas en 10 segundos.