
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 puedan hacer que los datos se envíen automáticamente a sus sistemas. Esto puede impulsar la automatización posterior, como la actualización de listas de correo, el inicio de viajes de correo electrónico automatizados o la populación de paneles internos. Aunque los mismos datos de eventos se pueden acceder a través de la interfaz de usuario de Bird utilizando Event Search, o de manera programática aprovechando la Events API de Bird, las limitaciones impuestas en el número de registros devueltos en una sola solicitud o las limitaciones de tasa en el endpoint 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 endpoint al que Bird transmite los datos, y los datos pueden consumirse sin tener que programar cron jobs que extraen los datos. También existen consideraciones logísticas cuando se extraen los datos en lugar de hacer que los datos se envíen a ti, 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 endpoint tan pronto como estén disponibles dentro de Bird.
Aunque los beneficios de recibir datos de eventos en tiempo real para impulsar los procesos de automatización posteriores puedan ser comprendidos de inmediato 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 endpoint y manejar los datos de manera programática. Hay servicios disponibles que consumirán los datos de webhook de Bird y realizarán ETL en tu base de datos automáticamente; un ejemplo sería StitchData, sobre el cual hemos blogueado en el pasado. Sin embargo, si deseas tener más control sobre el proceso, puedes construir fácilmente los componentes tú mismo. La siguiente es una guía simple 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.
Configuración del Endpoint de Webhook objetivo
Cuando se crea un evento de Bird, queremos que los datos de ese evento se transmitan en tiempo real a un endpoint en AWS para que podamos consumir y usar esos datos programáticamente. Los datos serán enviados desde Bird a un endpoint objetivo, que reenviará la carga útil a una función lambda que procesará y almacenará los datos en un bucket de S3. Un diagrama de alto nivel del flujo de datos descrito se puede ver a continuación:

Para implementar este flujo de trabajo, realmente construyámoslo en orden inverso comenzando con la creación de un bucket de S3 donde almacenaremos nuestros datos de eventos y luego trabajaremos hacia atrás, agregando cada componente que alimenta lo que hemos construido.
Crea un Bucket de 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 de S3 donde los datos se almacenarán. Para hacer esto, navega al servicio S3 dentro de AWS y presiona “Crear Bucket”. Se te pedirá asignar un nombre a tu bucket y establecer la región; asegúrate de usar la misma región que tu ALB y la función lambda. Cuando se crea tu bucket de S3, estará vacío; si deseas organizar los datos dentro de una carpeta, puedes crear el directorio previsto ahora, o el directorio se creará cuando tu función lambda almacene el archivo. En este ejemplo, nombramos nuestro bucket de S3 “bird-webhooks” y creamos una carpeta llamada “B Event Data” para almacenar nuestros datos de eventos; verás estos nombres referenciados en nuestra función lambda a continuación.
Crea una Función Lambda para Consumir los Datos
El procesamiento y almacenamiento real de los datos será realizado por una función lambda que es invocada por nuestro balanceador de carga de aplicación (ALB).
El primer paso es crear tu función lambda navegando al servicio Lambda dentro de AWS y haciendo clic en “Crear Función”. Se te pedirá asignar un nombre a tu función lambda y seleccionar qué lenguaje de programación escribirás tu función. Para este ejemplo, usamos Python como el lenguaje de ejecución.
Ahora necesitamos desarrollar nuestra función lambda. Por un momento, supongamos que nuestro balanceador de carga de aplicación ha sido configurado y está reenviando la carga útil del webhook a nuestra función lambda; la lambda recibirá una carga que incluye los encabezados completos y el cuerpo. La carga se pasa a nuestra función lambda usando el objeto “event” como un diccionario. Puedes hacer referencia a los encabezados y al cuerpo de la carga de manera 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 usarlo como el nombre del archivo al almacenar el cuerpo como un archivo plano en S3; sin embargo, es posible que desees 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 de 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 cual ayuda a asegurar que los datos se recojan y almacenen antes de que la conexión HTTP entre Bird y tu endpoint expire. Aunque podrías ajustar la configuración de tiempo de espera de conexión en tu balanceador de carga, no hay garantías de que la conexión no expire del lado de la transmisión (en este caso Bird) o que la conexión no se termine antes de que tu función lambda termine de ejecutarse. Es una buena práctica mantener tu función consumidora lo más eficiente posible y reservar las actividades de procesamiento de datos para procesos posteriores donde sea posible; como convertir la carga de trabajo en formato JSON por lotes en un archivo CSV, o cargar los datos de eventos en una base de datos.
Es importante tener en cuenta que es posible que necesites actualizar los permisos para tu función lambda. Tu rol de ejecución necesitará permisos de PutObject y GetObject para S3. Es una buena práctica aplicar el principio de privilegio mínimo, por lo que recomiendo establecer estos permisos solo para el bucket de S3 donde se almacenarán las cargas de los webhooks.
Una muestra de nuestra función lambda consumidora se puede encontrar aquí.
Una nota rápida sobre el ID de lote: Bird agrupará eventos en una sola carga, donde cada lote puede contener de 1 a 350 o más registros de eventos. Al lote se le dará un ID de lote único, que puede ser usado para ver el estado del lote aprovechando la API de Webhooks de Eventos o dentro de tu cuenta de Bird haciendo clic en un stream de webhook y seleccionando “Estado del Lote”. En el caso de que una carga de webhook no pudiera ser entregada, como durante un tiempo de espera de conexión, Bird automáticamente reintentará el lote usando el mismo ID de lote. Esto puede suceder cuando tu función lambda está ejecutándose cerca del tiempo máximo de ida y vuelta de 10 segundos y es una razón para optimizar la función consumidora 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 cuando se crea un nuevo archivo en el bucket de S3; de esta manera, el procesamiento de datos se realiza de forma asincrónica a la transmisión de los datos, y no hay riesgo de perder datos debido a una conexión terminada. Hablo sobre la función lambda de procesamiento en una sección posterior.
Crea un Balanceador de Carga de Aplicación
Para recibir una carga de webhook, necesitamos proporcionar un endpoint al cual enviar las cargas. Hacemos esto creando un balanceador de carga de aplicación dentro de AWS navegando a EC2 > Balances de Carga y haciendo clic en “Crear Balanceador de Carga”. Se te pedirá elegir qué tipo de balanceador de carga deseas crear; para esto, queremos crear un balanceador de carga de aplicación. Necesitamos usar un balanceador de carga de aplicación (ALB) para construir nuestro consumidor porque los webhooks de eventos se enviarán como solicitudes HTTP, y los ALB se usan 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 eliges utilizar un Gateway HTTP, el formato del evento puede ser diferente al de un ALB, y por lo tanto tu función lambda necesitará manejar el objeto de solicitud en consecuencia.
Una vez que tu ALB haya sido creado, se te pedirá asignar un nombre a tu ALB y configurar los ajustes de esquema y acceso/seguridad; dado que planeamos recibir datos de eventos de una fuente externa (Bird), querremos que nuestro ALB sea orientado a Internet. Bajo “Listeners y enrutamiento”, el ALB debería 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 solicitudes entrantes a la función lambda consumidora que creamos anteriormente. También necesitas asegurarte de que el grupo de seguridad tiene permiso para aceptar tráfico a través del puerto 443.
Crea un Registro DNS para el Balanceador de Carga
Para facilitar 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 tu proveedor de DNS actual) y crear un registro A para el nombre de host que deseas usar para tu endpoint (por ejemplo, spevents.<tu_dominio>). El registro A debe ser configurado para apuntar al ALB que creamos. Si estás usando Route 53 para manejar los registros DNS, puedes referenciar la instancia ALB directamente habilitando “Alias” y seleccionando el ALB; de lo contrario, si estás usando un proveedor de DNS externo, debes apuntar el registro A a la dirección IP pública de la instancia ALB.
Recomiendo usar una herramienta como Postman para probar que todo ha sido configurado correctamente antes de habilitar tu webhook de Bird. Puedes hacer una solicitud POST a tu endpoint y confirmar que se reciba una respuesta. Si tu solicitud POST no devuelve una respuesta, es posible que debas verificar que tu ALB está escuchando en el puerto correcto.
Crea 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 objetivo. Para crear el webhook, navega a la sección de Webhooks dentro de tu cuenta de Bird y haz clic en “Crear Webhook”. Se te pedirá asignar un nombre a tu webhook y proporcionar una URL objetivo; el objetivo debe ser el nombre de host del registro A que creaste anteriormente. Nota que la URL objetivo puede requerir que “HTTPS://” esté incluido en la URL.
Una vez que esté completo, verifica que la subcuenta y los eventos correctos estén seleccionados, y presiona “Crear Webhook” para guardar tu configuración. Los datos de evento para todos los tipos de evento seleccionados ahora se transmitirán a nuestra URL objetivo y serán consumidos por nuestro ALB para procesamiento posterior.