¿Hay alguna forma de enviar notificaciones por correo electrónico más rápido?

Tenemos una categoría #Announcements en la que todos nuestros miembros están suscritos automáticamente para ver la primera publicación.

Esto nos permite programar la publicación de entradas en esa categoría en momentos/fechas determinadas.

A su vez, el anuncio se envía por correo electrónico a unos 25.000 miembros.

El problema que tenemos es que los correos electrónicos tardan más de una hora en enviarse, lo que no es ideal para anuncios críticos en cuanto al tiempo.

Si observo Sidekiq, puedo ver que el contador “Scheduled” acumula todos los correos electrónicos individuales uno por uno; una vez que llega a unos 20.000, los traslada a la pestaña “Enqueued” y, finalmente, comienzan a enviarse.

¿Hay alguna forma de acelerar este proceso? :thinking:

Para correos electrónicos críticos en cuanto al tiempo, sería bueno enviarlos unas 100 veces más rápido de lo que van actualmente :blush:

Esta discusión puede ayudarte, ya que explica cómo establecer DISCOURSE_MAX_DIGESTS_ENQUEUED_PER_30_MINS_PER_SITE, que define el límite global para los resúmenes.

2 Me gusta

Lo cronometré esta noche.

Programé una publicación para que se publicara en la categoría #Announcements a las 18:30.


A las 18:40 había 15.000 correos electrónicos en la cola Scheduled.


A las 18:45, es decir, 15 minutos después de la publicación, había 22.000 correos electrónicos en la cola Scheduled.


A las 18:48, esos correos electrónicos comenzaron a moverse gradualmente a la cola Enqueued:


A las 18:51 todavía se estaban moviendo:


A las 19:03 los correos electrónicos estaban en camino:


A las 19:10 quedaban solo 10.000 correos electrónicos:


A las 19:27 quedaban solo 569 correos electrónicos:


Y a las 19:29 se habían enviado todos los correos electrónicos:


Así que ahí lo tienen, una hora completa para enviar 22.000 notificaciones por correo electrónico.

¿Alguien puede ayudarme a identificar el cuello de botella aquí?

Me gustaría mucho poder enviar estos correos electrónicos más rápido que su tasa actual de 22.000 por hora.

Disparando sobre la marcha,
¿Es posible que sea un problema de carga de infraestructura?

1 me gusta

¿Quizás?

Realmente no lo sé :person_shrugging:
La CPU se disparó a alrededor del 44% en el servidor:

Y uso AWS SES para el SMTP.

Aquí están sucediendo dos cosas:

  • retraso mientras se ponen en cola los trabajos de correo electrónico
  • tiempo de procesamiento para enviar el correo electrónico real

Para lo primero, no estoy 100% seguro de esto, pero creo que reducir email_time_window_mins significa que las notificaciones se ponen en cola antes.

Una vez que los trabajos de correo electrónico están programados, sus trabajadores de sidekiq los procesan uno a la vez. Aumentar los trabajadores de sidekiq (establecer DISCOURSE_SIDEKIQ_WORKERS de 5 a 10, 15 o 20 según la capacidad del servidor) significa que se procesan más trabajos al mismo tiempo, por lo que la cola se vacía 2x/3x/4x más rápido.

4 Me gusta

No sé cómo funciona el backend con el mayor detalle, pero email_time_window_mins es solo una configuración de retraso antes de que salga el primer correo electrónico. Durante este tiempo, cualquier usuario que esté configurado para recibir el correo electrónico puede “renunciar” al correo electrónico si resulta estar activo dentro de la ventana de período (terminología oficial: correo electrónico omitido; motivo de omisión: El usuario fue visto recientemente).

El retraso predeterminado es de 10 minutos, lo que significa que la publicación debe estar activa durante 10 minutos y solo entonces se enviarán los correos electrónicos.

El problema de Richie es la diferencia de tiempo entre el primer correo electrónico y el último… un retraso de una hora. Esto se debe probablemente a la gran cantidad de correos electrónicos que deben enviarse, aunque tampoco puedo decirlo con certeza.

Cambiar la configuración anterior solo aceleraría el envío del primer correo electrónico, pero no abordaría la duración de finalización del lote completo de 22.000 correos electrónicos.


¿Cuál sería la configuración recomendada, obviamente dependiente de la capacidad de la infraestructura?

¿Podría una configuración alta resultar en problemas del servidor en términos de carga u otros?

1 me gusta

“Tantos como el servidor pueda manejar”.

Depende al 100% de la capacidad del servidor del OP: demasiados y ralentizará las cosas, muy pocos y tardará más en procesarse.

Dado que el gráfico de la CPU alcanza el 40% (¿es de una sola CPU o de la capacidad total?), probablemente comenzaría aumentando 2 veces (conservador) o 3 veces (agresivo) y vería qué sucede, dependiendo de la tolerancia al riesgo de ralentizaciones.

1 me gusta

Gran perspectiva, gracias :slight_smile:

¿Tiene que ser DISCOURSE_SIDEKIQ_WORKERS un múltiplo de 5? ¿Podría establecerlo en 7, por ejemplo?

No tengo esa configuración de parámetro en mi app.yml, así que asumiré que está en un valor predeterminado de 5 en algún lugar.

¿Puedo simplemente crear esa configuración debajo de la configuración existente de workers de unicorn, y luego reconstruir?

Por ejemplo:

expose:
  - "443:443"

env:
  UNICORN_WORKERS: 8
  DISCOURSE_SIDEKIQ_WORKERS: 7

¿Es tan simple como eso? :thinking:

¿Alguien puede confirmar si este es el cambio correcto a realizar en mi app.yml cuando el parámetro DISCOURSE_SIDEKIQ_WORKERS no existe actualmente?

1 me gusta

Creo que sí, tras una breve consulta al bot de IA.

1 me gusta

Gracias @TempAccount

Curiosamente, DISCOURSE_SIDEKIQ_WORKERS solo aparece once veces en todo meta:

Search results for '"DISCOURSE_SIDEKIQ_WORKERS" order%3' - Discourse Meta বৈশিষ্ট্যের_topic

…y una de esas es en este tema :cara_sonrojada:

Sí, esto es correcto.

Cualquier (¿la mayoría?) configuración se puede anular de esta manera. El valor predeterminado proviene de discourse_defaults.conf.

2 Me gusta

Gracias @supermathie

Mi app.yml ahora dice:

env:
  LANG: en_US.UTF-8
  # DISCOURSE_DEFAULT_LOCALE: en

  ## ¿Cuántas solicitudes web concurrentes se admiten? Depende de la memoria y los núcleos de CPU.
  ## se establecerá automáticamente mediante bootstrap según las CPU detectadas, o puede anularlo
  UNICORN_WORKERS: 8

  ## Añadí esta línea el 04/10/25
  ## REF: https://meta.discourse.org/t/is-there-a-way-i-can-send-email-notifications-faster/383103/12
  DISCOURSE_SIDEKIQ_WORKERS: 7

Reconstruiré más adelante esta semana y cronometraré el envío de correos electrónicos :smiley:

Solo para saber si mi cambio ha surtido efecto, ¿estoy en lo cierto al pensar que este valor Threads debería aumentar de 5 a 7?

2 Me gusta

Sí, confirmado:

2 Me gusta

@Richie ¿pudiste resolver tu problema?

Gracias por dar seguimiento.

No, lamentablemente no.

He aumentado los hilos de 5 a 8, pero los correos electrónicos aún tardan casi una hora en enviarse de principio a fin.

Esperaría quizás un aumento del 40% en el rendimiento total.

Cuando los trabajos están en cola, ¿ves una utilización del 7/7?

Además, observa la carga del servidor cuando los está procesando, y si puedes aumentarla aún más, te lo recomiendo.

Ohhhhhh espera un minuto. ¿Discourse se está limitando de alguna manera?

¿Me he saltado alguna configuración que restrinja su uso de CPU? :scream:

No se limita por sí mismo, sino que cada trabajador de sidekiq procesará un trabajo a la vez, por lo que si tienes 22000 correos electrónicos esperando para ser enviados, siete de ellos se procesarán a la vez.

En el lado ridículo de las cosas, el servidor probablemente no podrá seguir el ritmo si estableces el número en 1000 trabajadores paralelos. Así que se trata de encontrar un número que se adapte a todas tus necesidades:

  • procesar tantos trabajos como sea posible al mismo tiempo para poder enviar los 22000 correos electrónicos más rápido
  • pero no consumir TODOS los recursos del servidor, lo que dejaría ninguno para los usuarios del sitio
2 Me gusta