
Lo siguiente es una guía sencilla para ayudar a los remitentes a sentirse cómodos al crear un webhook de eventos de Bird y consumir los datos utilizando la infraestructura de AWS.
Los webhooks de eventos en tiempo real de Bird son una herramienta increíblemente valiosa para que los remitentes tengan datos automáticamente enviados a sus sistemas. Esto puede impulsar la automatización posterior, como actualizar listas de correo, activar recorridos de correo electrónico automatizados o poblar paneles internos. Aunque los mismos datos de eventos pueden accederse a través de la UI de Bird usando Event Search, o programáticamente utilizando la Events API de Bird, las limitaciones impuestas en el número de registros devueltos en una sola solicitud o los límites de tasa impuestos en el punto final de la API pueden hacer que ambos métodos sean restrictivos para remitentes grandes y sofisticados.
Los webhooks de eventos en tiempo real permiten a un remitente configurar un punto final al que Bird transmite los datos, y los datos pueden ser consumidos sin tener que programar trabajos cron que extraigan los datos. También hay compromisos logísticos al extraer los datos en lugar de recibirlos, como tener que identificar qué período de tiempo y parámetros usar para cada solicitud de API. Si los períodos de tiempo no están perfectamente alineados, corres el riesgo de perder datos, y si los períodos de tiempo se superponen, entonces necesitas manejar registros de datos duplicados. Con los webhooks en tiempo real, los datos de eventos simplemente se envían a tu punto final a medida que están disponibles dentro de Bird.
Aunque los beneficios de recibir datos de eventos en tiempo real para impulsar procesos de automatización posterior pueden ser comprendidos inmediatamente por muchos remitentes, el proceso real para implementar y consumir webhooks puede ser intimidante. Esto puede ser especialmente cierto si no estás familiarizado con los componentes técnicos de crear un punto final y manejar los datos programáticamente. Hay servicios disponibles que consumen los datos del webhook de Bird y ejecutan ETL en tu base de datos automáticamente, un ejemplo sería StitchData, sobre lo cual hemos escrito en el pasado. Sin embargo, si prefieres tener más control sobre el proceso, puedes fácilmente construir los componentes tú mismo. Lo siguiente es una guía sencilla para ayudar a los remitentes a sentirse cómodos al crear un webhook de eventos de Bird y consumir los datos utilizando la infraestructura dentro de AWS.
Configuración del Endpoint de Webhook objetivo
Cuando se crea un evento de Bird, queremos que esos datos del evento se transmitan en tiempo real a un endpoint en AWS para que podamos consumir y usar esos datos programáticamente. Los datos se enviarán desde Bird a un endpoint de destino, que reenviará la carga a una función lambda que procesará y almacenará los datos en un bucket S3. A continuación, se puede ver un diagrama de alto nivel del flujo de datos descrito:

Para implementar este flujo de trabajo, construiremos realmente a la inversa comenzando con la creación de un bucket S3 donde almacenaremos nuestros datos de eventos y luego trabajaremos hacia atrás, agregando cada componente que alimenta lo que hemos construido.
Crear un Bucket S3 para Almacenar los Datos del Webhook
Antes de crear nuestro balanceador de carga para aceptar los datos, o nuestra función lambda para almacenarlos, primero necesitamos crear nuestro bucket S3 donde se almacenarán los datos. Mientras que S3 proporciona un excelente almacenamiento para los datos de webhook, las organizaciones que también usan bases de datos PostgreSQL para el procesamiento de eventos deben implementar adecuadas procedimientos de respaldo y restauración para proteger sus datos estructurados junto con su estrategia de almacenamiento en S3. Para hacer esto, navegue al servicio S3 dentro de AWS y presione "Create Bucket." Se le pedirá asignar un nombre a su bucket y establecer la región, asegurándose de usar la misma región que su ALB y función lambda. Cuando se crea su bucket S3, estará vacío: si desea organizar los datos dentro de una carpeta, puede crear el directorio deseado ahora, o el directorio se creará cuando su función lambda almacene el archivo. En este ejemplo, nombramos nuestro bucket S3 "bird-webhooks" y creamos una carpeta llamada "B Event Data" para almacenar nuestros datos de eventos: verá estos nombres referenciados en nuestra función lambda a continuación.
Crear una Función Lambda para Consumir los Datos
El procesamiento y almacenamiento real de los datos serán realizados por una función lambda invocada por nuestro balanceador de carga de aplicaciones (ALB).
El primer paso es crear su función lambda navegando al servicio Lambda dentro de AWS y haciendo clic en "Create Function." Se le pedirá asignar un nombre a su función lambda y seleccionar en qué lenguaje de programación escribir su función. Para este ejemplo, usamos Python como el lenguaje de ejecución.
Ahora necesitamos desarrollar nuestra función lambda. Por un momento, asumamos que nuestro balanceador de carga de aplicaciones ha sido configurado y está reenviando la carga del webhook a nuestra función lambda. La lambda recibirá una carga que incluye todos los encabezados y el cuerpo. La carga se pasa a nuestra función lambda utilizando el objeto "event" como un diccionario. Puede acceder a los encabezados y el cuerpo de la carga de forma independiente accediendo a los objetos "headers" y "body" dentro de la carga. En este ejemplo, simplemente vamos a leer el encabezado "x-messagesystems-batch-id", donde el ID de lote es un valor único creado por Bird para el lote del webhook, y lo usaremos como el nombre del archivo al almacenar el cuerpo como un archivo plano en S3; sin embargo, es posible que desee agregar funcionalidades adicionales como verificaciones de autenticación o manejo de errores, según sea necesario.
Al almacenar la carga en un archivo plano en S3, necesitaremos definir el nombre del bucket S3, la ubicación y el nombre del archivo donde se almacenarán los datos de la carga. En nuestra función lambda de muestra, hacemos esto dentro de la función "store_batch." En este ejemplo, vamos a almacenar todo el lote como un solo archivo, lo que ayuda a asegurar que los datos se recolecten y almacenen antes de que la conexión HTTP entre Bird y su endpoint se agote. Aunque podría ajustar la configuración de tiempo de espera de la conexión en su balanceador de carga, no hay garantías de que la conexión no se agote en el lado de la transmisión (en este caso Bird) o que la conexión no se termine antes de que su función lambda termine de ejecutarse. Es una buena práctica mantener su función de consumo lo más eficiente posible y reservar actividades de procesamiento de datos para procesos posteriores cuando sea posible, como convertir la carga en formato JSON por lotes a un archivo CSV, o cargar los datos del evento en una base de datos.
Es importante tener en cuenta que es posible que necesite actualizar los permisos para su función lambda. Su rol de ejecución necesitará permisos PutObject y GetObject para S3. Es una buena práctica aplicar el principio del menor privilegio, por lo que recomiendo establecer estos permisos solo para el bucket S3 donde se almacenarán las cargas del webhook.
Una muestra de nuestra función lambda de consumo se puede encontrar aquí.
Una nota rápida sobre el ID de lote: Bird acumulará eventos en una sola carga, donde cada lote puede contener de 1 a 350 o más registros de eventos. El lote recibirá un ID de lote único, que se puede utilizar para ver el estado del lote aprovechando el API de Webhooks de Eventos o dentro de su cuenta de Bird haciendo clic en un stream de webhook y seleccionando "Estado del Lote." En el caso de que una carga del webhook no pudiera ser entregada, como durante un tiempo de espera de conexión, Bird automáticamente volverá a intentar el lote usando el mismo ID de lote. Esto puede suceder cuando su función lambda está corriendo cerca del tiempo máximo de ida y vuelta de 10 segundos y es una razón para optimizar la función de consumidor para reducir el tiempo de ejecución.
Para manejar todas las actividades de procesamiento de datos, recomiendo crear una función lambda separada que se ejecute cada vez que se crea un nuevo archivo en el bucket S3; de esta manera, el procesamiento de datos se realiza de forma asincrónica con la transmisión de los datos y no hay riesgo de perder datos debido a una conexión terminada. Discuto la función lambda de procesamiento en una sección posterior.
Crear un Balanceador de Carga de Aplicaciones
Para recibir una carga del webhook, necesitamos proporcionar un endpoint para enviar las cargas. Hacemos esto creando un balanceador de carga de aplicaciones dentro de AWS navegando a EC2 > Load Balancers y haciendo clic en "Create Load Balancer." Se le pedirá elegir qué tipo de balanceador de carga desea crear, para esto, queremos crear un balanceador de carga de aplicaciones. Necesitamos usar un balanceador de carga de aplicaciones (ALB) para construir nuestro consumidor porque los webhooks de eventos se enviarán como una solicitud HTTP, y los ALB se utilizan para enrutar solicitudes HTTP dentro de AWS. Podríamos implementar un Gateway HTTP como alternativa; sin embargo, usamos un ALB para este proyecto porque es más liviano y rentable que el Gateway HTTP. Es importante señalar que si elige usar un Gateway HTTP, el formato del evento puede ser diferente al de un ALB, y por lo tanto su función lambda necesitará manejar el objeto de solicitud en consecuencia.
Una vez que su ALB ha sido creado, se le pedirá asignar un nombre a su ALB y configurar el esquema y las configuraciones de acceso/seguridad, ya que planeamos recibir datos de eventos de una fuente externa (Bird), queremos que nuestro ALB sea accesible por Internet. Bajo "Listeners and routing", el ALB debe escuchar HTTPS en el puerto 443, y queremos crear un grupo de destino que apunte a nuestra función lambda para que nuestro ALB reenvíe las solicitudes entrantes a la función lambda de consumo que creamos anteriormente. También debe asegurarse de que el grupo de seguridad tenga permiso para aceptar tráfico a través del puerto 443.
Crear un Registro DNS para el Balanceador de Carga
Para facilitarnos el uso de nuestro ALB como un endpoint, crearemos un registro A en DNS que apunte a nuestro ALB. Para esto, podemos usar el servicio AWS Route 53 (o su proveedor de DNS actual) y crear un registro A para el nombre de host que desea usar para su endpoint (por ejemplo, spevents.<your_domain>). Cuando se trabaja con DNS a escala en AWS, tenga en cuenta que hay límites de DNS no documentados que pueden afectar a aplicaciones de alto volumen, especialmente aquellas que manejan grandes cantidades de tráfico saliente como sistemas de entrega de correo electrónico. El registro A debe configurarse para apuntar al ALB que creamos. Si está usando Route 53 para administrar los registros de DNS, puede hacer referencia directamente a la instancia de ALB habilitando "Alias" y seleccionando el ALB; de lo contrario, si está utilizando un proveedor de DNS externo, debe apuntar el registro A a la dirección IP pública de la instancia de ALB.
Recomiendo usar una herramienta como Postman para probar que todo se ha configurado correctamente antes de habilitar su webhook de Bird. Puede hacer una solicitud POST a su endpoint y confirmar que se recibe una respuesta. Si su solicitud POST no devuelve una respuesta, es posible que deba verificar que su ALB esté escuchando en el puerto correcto.
Crear un Webhook de Bird
Ahora estamos listos para crear el webhook en Bird y usar el nombre de host definido por el registro A anterior como nuestro endpoint de destino. Para crear el webhook, navegue a la sección de Webhooks dentro de su cuenta de Bird y haga clic en "Create Webhook." Se le pedirá asignar un nombre para su webhook y proporcionar una URL de destino, el destino debe ser el nombre de host del registro A que creó anteriormente. Tenga en cuenta que es posible que se requiera incluir "HTTPS://" en la URL.
Una vez completado, verifique que la subcuenta y eventos correctos estén seleccionados, y presione "Create Webhook" para guardar su configuración. Los datos del evento para todos los tipos de eventos seleccionados ahora fluirán a nuestra URL de destino y serán consumidos por nuestro ALB para procesamiento posterior.