
No es ningún secreto que me he desconectado de WP Descargar SES, un nuevo complemento que esperamos lanzar pronto, que facilitará el envío de correos electrónicos a su sitio a través de Amazon SES. Aunque lo mencioné anteriormente en este blog, una cosa que no mencioné es el rendimiento que puede esperar lograr. En el artículo de esta semana, decidí dar un paso atrás por un segundo y revisar el sistema de espera que instalé y cómo logré apretar el último gramo. La planificación de las cosas que sabíamos desde el principio que tenemos que implementar una cola de correo electrónico, de modo que, en lugar de enviar correos electrónicos de inmediato, estarán en línea y se procesarán en lotes. Los servidores SMTP generalmente tendrán una cola construida, pero debido a que usamos la API de Amazon SES en lugar de SMTP, debemos lanzar nuestra propia solución.
Sin una cola, nos enfrentamos a situaciones en las que el sitio está tratando de enviar cientos, si no miles de correos electrónicos simultáneamente, y esto inevitablemente conduciría a un bloqueo debido a la falta de memoria o tiempo para procesar la solicitud. Además, el límite de la tasa de SES de Amazon, que no se establece en la piedra y varía de la cuenta, debe tenerse en cuenta. Una vez que nos dimos cuenta de que deberíamos construir una cola, mi mente fue directamente a WP Queue, una biblioteca de arado de WordPress construida por nuestra propia Ashley Rich. También lo usé en algunos otros complementos, como el suplemento WP de los archivos DB Pro Theme + Plugin y el complemento de cola de procesamiento de imágenes.
¿Por qué WP Queue? Hace un gran trabajo para permitirle registrar un trabajo y agregar más colas a la cola, que luego se transmiten a través de WP-Chron. Miré algunos otros sistemas de cola e incluso busqué el servicio de cola de Amazon. Sin embargo, decidí en contra de esto debido al precio adicional y la complejidad de tener otro servicio para confiar. Además, si alguna vez necesitábamos hacer ajustes o cambios en el sistema de cola, es mucho más fácil hacerlo con WP Queue que para Amazon SQS. AWS Commandpool Una pequeña desventaja de usar la cola de WP para nuestras necesidades es que se centra en completar un trabajo en un punto, en el principio del primero, por primera vez. Esto es simple y funciona, pero podría ser lento para los usuarios que tienen la intención de enviar miles de correos electrónicos al día. Debido a que la solicitud de API promedio a Amazon SES puede demorar aproximadamente 0.4 segundos, podemos esperar enviar solo unos pocos correos electrónicos por segundo. Para evitar esto, AWS recomienda usar más hilos para enviar más correos electrónicos al mismo tiempo, en lugar de enviar uno y esperar la respuesta antes de enviar otro. Afortunadamente, Amazon ha creado una forma de hacer esto exactamente en el PHP SDK que usa el SES de descarga de WP. El objeto Commandpool se puede usar para agregar manualmente una serie de comandos que se enviarán a la API y los agrupará de manera inteligente.
Al ver el flujo con la decisión del sistema de cola, es mucho más fácil ver el flujo de datos en el complemento para enviar correos electrónicos:
Implementación ahora, para la parte divertida: ¡la implementación efectiva del sistema! Sobrescrito wp_mail () El primer paso fue sobrescribir la función wp_mail (), que es una función conectada de WordPress. Esto nos permite escuchar todos los correos electrónicos enviados a través de WordPress (y los temas y complementos de acuerdo) y usar nuestra propia funcionalidad en lugar de enviar el correo electrónico de inmediato. En la descarga de WP SES, esto es bastante simple: solo agregamos el siguiente código en la parte inferior del archivo del complemento principal: if (! Function_exists (‘wp_mail’)) {$ settings = get_site_option (‘wposeS_settings’); if (isset ($ settings [‘send-via-ses’) && (bool) $ settings [‘send-via-ses’) {function wp_mail ($ to, $ temas, $ mensaje, $ encabezados = ”, $ Attachments = array ()) {global $ wp_offload_ses; $ wp_offload_ses-> mail_handler ($ to, $ temas, $ mensaje, $ encabezados, $ archivos adjuntos); }}} La anterior verifica que la función wp_mail () ya se ha sobrescribida, y si no, crea nuestro propio wp_mail () si el complemento de descarga WP SES está configurado para enviar correo electrónico.

Acepta todos los mismos datos que la función WP_Mail () original y los envía a nuestro controlador de correo electrónico personalizado.Agregue a la cola luego, debemos agregar el correo electrónico a la cola.El método mail_hander () nombrado en la función wp_mail () anterior combina todos los atributos transmitidos a wp_mail () y presiona un nuevo correo electrónico en la cola: función pública mail_handler ($ to, $ asunto, $ mensaje, $ encabezados, $ accesorios) {$ ATTS = APLICE_FILTERS (‘wp_mail’, compact (‘a’, ‘sujeto,’ mensaje ‘,’ encabezados ‘,’ adjuntos ‘));$ settings = $ this-> settings-> get_settings ();$ this-> get_queue ()-> push (nuevo correo electrónico_job ($ atts, $ configuración), $ this-> demandado);devolver verdadero;} Esto guarda el trabajo de correo electrónico en la base de datos que se procesará más adelante.Hablando sobre el trabajo por correo electrónico, esto es lo que parece:
Class email_job extiende el trabajo { / ** * @var array * / private $ atts; / ** * @Var Array */ private $ configuración; /*** Pase cualquier fecha de necesidad al trabajo. * * @param cadena $ atts */ public function __construct ($ atts, $ settings) {$ this-> atts = $ atts; $ this-> configuración = $ configuración; } /*** Maneje la lógica de trabajo. */ Public Function Handle () {Global $ wp_offload_ses; if (isset ($ this-> atts [‘to’])) {$ to = $ this-> atts [‘to’]; } if (isset ($ this-> atts [‘sujeto’)) {$ sujeto = $ this-> atts [‘sujeto’]; } If (isset ($ this-> atts [‘mensaje’)) {$ mensaje = $ this-> atts [‘mensaje’]; } if (isset ($ this-> atts [‘encabezados’)) {$ headers = $ this-> atts [‘encabezados’]; } If (isset ($ this-> atts [‘adjuntos’])) {$ adjuntos = $ this-> atts [‘adjuntos’]; } $ Client = $ wp_offload_ses-> get_ses_pi ()-> get_client (); $ correo electrónico = nuevo correo electrónico ($ a, $ asunto, $ mensaje, $ encabezados, $ archivos adjuntos, $ this-> configuración); $ raw = $ correo electrónico-> preparar (); $ dat = array (‘x-message -id’ => $ this-> id (), ‘rawmesage’ => array (‘data’ => $ raw,),); Devolver $ client-> getCommand (‘sendrawail’, $ fecha); }} Cuando la cola procesa los empleos, restaurará la clase Email_JOB de la base de datos con los atributos transmitidos al constructor y luego llamará al método Process () para ejecutar el trabajo.
En este caso, recibe un envío listo para ser enviado y devuelve la orden de enviarlo de manera efectiva, se usa más adelante en Commandpool.Enviar a través de Commandpool Afortunadamente, el AWS PHP SDK incluye las clases necesarias para comenzar a usar Commandpool sin demasiados cambios adicionales.Hemos creado una clase que trata con toda la lógica relevante que tiene tres métodos principales.Primero, está add_command (), que agrega un orden al grupo: función pública add_command ($ command) {$ this-> comandos [] = $ command;$ num_commands = count ($ this-> comandos);if ($ this-> get_concurrency () === $ num_commands$ This-> comandos = array ();}} Entonces, cuando se alcanzó un límite de comando, se llama la función ejecutada ():
Función privada ejecutada () {global $ wp_offload_ses; // inició el commandpool $ client = $ wp_offload_ses-> get_ses_pi ()-> get_client (); $ Command_pool = new CommandPool ($ Client, $ this-> comandos, [‘competencia’ => $ this-> get_concurrency (), ‘fullfilled’ => function (resulTrace $ resultado, $ iterkey, promesa $ agregatePromise) {$ id = $ this-> comandos [$ iterkey] [‘X-Message -id’]; $ Job = $ this-> Connection-> get_job ($ id); $ this-> conexión-> delete ($ trabajo);} , ‘Rechazado’ => función (Sesexception $ Razon > get_job ($ id); $ trabajo-> relay (); if ($ job-> intentos ()> = $ this-> intentos) {$ job-> fail ();} if ($ trabajo-> fallado ( )) {$ this-> Connection-> faily ($ Job, $ razon);} else {$ this-> conexión-> relay ($ trabajo);}}); // Envía el correo electrónico en el grupo $ promety = $ command_pool-> promise (); $ promise-> wait (); } Esta característica inicia la clase AWS Commandpool y envía solicitudes de manera asíncrona. Lo hermoso es que también puede aprobar funciones anónimas para administrar las respuestas a las solicitudes de API, de modo que cada solicitud se administre tan pronto como se complete, en lugar de esperar que se envíen todas las solicitudes. La función anónima cumplida gestiona las solicitudes que se han completado con éxito y las elimina de la cola, mientras que la función de rechazo gestiona las aplicaciones fallidas y emite el trabajo que se intentará nuevamente. Si una solicitud falla más de un cierto número de veces (en este caso 3), se marca como fallido y no se retirará automáticamente.

Es posible que haya notado que la competencia Commandpool está establecida por otra característica, get_concurrency (). Esta función se hace cargo de la tasa de referencia máxima de SES y la transmite al objeto Commandpool, asegurando que siempre se ejecute a la capacidad máxima sin exceder la tasa de SES de Amazon: función privada get_concurrency () {global $ wp_offload_ses; if (! is_ull ($ this-> competencia)) {return $ this-> competencia; } $ cuota = $ wp_offload_ses-> get_ses_pi ()-> get_send_quot (); $ Send_rate = 10; if (! is_wp_error ($ cuota)) {$ send_rate = $ cuota [‘tarifas’]; } $ this-> competencia = (int) aplica_filters (‘wposes_max_concurrency’, $ send_rate); Devolver $ this-> competrencia; } La cola continuará pasando por los trabajos de correo electrónico disponibles hasta que ya no sean trabajos o se alcanza el límite de tiempo de PHP. Una vez que esto sucede, la cola se detiene hasta el siguiente rodamiento de WP_CRON y luego continúa el procesamiento de aplicaciones. Benchmarking con todo el código activado, es hora de ver si todo realmente funciona. Debido a que es difícil comparar solicitudes asincrónicas con una API remota, creamos un script rápido que pondría la cola de varios cientos de correos electrónicos y cambiamos la función de comandos cumplido para grabar el tiempo que se envió cada correo electrónico. Después de algunos puntos de referencia, Se hizo evidente que estaba enviando fácilmente 100 correos electrónicos por segundo y supongo que enviaría aún más si Amazon aprueba mis solicitudes constantes para aumentar mi límite de tarifas.


homefinance blog