
以下是一个简单的指南,帮助发送者在创建鸟类事件Webhook时感到舒适,并使用AWS中的基础设施来消费数据。
Bird 的实时事件 webhooks 是发送方非常有价值的工具,可以将数据自动推送到他们的系统。这可以推动下游自动化,例如更新邮件列表、触发自动化电子邮件旅程或填充内部仪表板。虽然可以通过使用 Bird UI 的 事件搜索 或通过利用 Bird 事件 API以编程方式访问相同的事件数据,但对单个请求中返回的记录数量的限制或对 API 端点的速率限制可能会使这两种方法对大型和复杂的发送方来说都具有局限性。
实时事件 webhooks 使发送方能够配置一个终端,Bird 将数据传输到该终端,并且可以在不安排抓取数据的定时任务的情况下使用数据。与数据推送给你相比,拉取数据时也会有一些后勤权衡,比如必须为每个 API 请求确定使用的时间段和参数。如果时间段没有完美对齐,那么你有丢失数据的风险;如果时间段重叠,那么你需要处理重复的数据记录。使用实时 webhooks,事件数据在 Bird 中可用时会简单地推送到您的终端。
虽然许多发送者可能会立即理解实时接收事件数据以推动下游自动化流程的好处,但实施和使用 webhooks 的实际过程可能令人望而生畏。如果您不熟悉创建终端和以编程方式处理数据的技术组件,这尤其可能是真的。有服务可用于自动消耗 Bird webhook 数据并将其 ETL 到您的数据库中——例如我们过去写过博客的 StitchData。然而,如果您希望对该过程有更多控制权,您可以轻松地自己构建组件。以下是一个简单的指南,帮助发送者在使用 AWS 内的基础设施创建 Bird 事件 webhook 并使用数据时感到舒适。
配置 Webhook Target Endpoint
当一个 Bird 事件被创建时,我们希望将该事件数据实时流式传输到 AWS 中的一个终端,以便我们能够以编程方式消费和使用这些数据。数据将从 Bird 发送到目标终端,该终端会将负载转发到一个处理数据并将其存储在 S3 桶中的 lambda 函数。下方可以看到所描述的数据流的高级图解:

要实现这个工作流程,让我们实际上以逆序构建它们,从创建一个 S3 桶开始,我们将在其中存储我们的事件数据,然后向后工作 - 添加每个组件来支持我们构建的内容。
创建一个 S3 桶以存储 Webhook 数据
在创建接受数据的负载均衡器或存储数据的 lambda 函数之前,我们需要首先创建一个 S3 桶 来存储数据。为此,请导航到 AWS 的 S3 服务,并点击“创建桶”。系统会提示您为桶指定一个名称并设置区域 - 确保使用与您的 ALB 和 lambda 函数相同的区域。当您的 S3 桶被创建后,它将是空的 - 如果您想在文件夹中组织数据,您可以立即创建所需目录,也可以在 lambda 函数存储文件时创建该目录。在本例中,我们将我们的 S3 桶命名为“bird-webhooks”并创建了一个名为“B Event Data”的文件夹来存储我们的事件数据 - 您将在下面的lambda 函数中看到这些名称被引用。
创建一个 Lambda 函数以消费数据
数据的实际处理和存储将由一个 lambda 函数 执行,该函数由我们的应用负载均衡器(ALB)调用。
第一步是通过导航到 AWS 中的 Lambda 服务并点击“创建函数”来创建您的 lambda 函数。系统会提示您为 lambda 函数指定一个名称并选择编写函数的编程语言。在这个示例中,我们使用 Python 作为运行时语言。
现在我们需要开发我们的 lambda 函数。假设我们的应用负载均衡器已经配置好并正在将 webhook 负载转发到我们的 lambda 函数 - lambda 将接收一个包括完整头和正文的负载。负载通过“event”对象作为字典传递给我们的 lambda 函数。您可以通过访问负载内的“headers”和“body”对象来独立引用负载的头和正文。在此示例中,我们将读取“x-messagesystems-batch-id”头,其中批量 ID 是 Bird 为 webhook 批量创建的唯一值,并在将正文作为平面文件存储在 S3 时使用该值作为文件名;然而,您可能希望根据需要添加额外的功能,例如身份验证检查或 错误处理。
将负载存储为 S3 上的平面文件时,我们需要定义 S3 桶的名称、位置和存储负载数据的文件的文件名。在我们的示例 lambda 函数中,我们在“store_batch”函数中执行此操作。在这个示例中,我们将整个批量作为一个单一文件存储,这有助于确保在 Bird 和您的终端之间的 HTTP 连接超时之前收集和存储数据。虽然您可以调整负载均衡器上的连接超时设置,但不能保证连接不会在传输端(在这种情况下是 Bird)超时,也不能保证在 lambda 函数完成执行之前不终止连接。最好的做法是尽可能高效地保持您的消费者函数,并将数据处理活动保留给下游进程,例如将批量 JSON 格式负载转换为 CSV 文件,或将事件数据加载到数据库中。
重要的是,您可能需要更新 lambda 函数的权限。您的执行角色需要对 S3 的 PutObject 和 GetObject 权限。最好的做法是强制执行最小权限原则,因此我建议仅为存储 webhook 负载的 S3 桶设置这些权限。
我们的消费者 lambda 函数的示例可以在 这里 找到。
关于批量 ID 的简要说明:Bird 将 批次事件合并到一个负载中,每个批次可能包含 1 到 350 个或更多事件记录。批次会被分配一个唯一的批次 ID,可以通过利用事件 Webhooks API 或进入您的 Bird 账户点击webhook 流并选择“批量状态”查看批次状态。如果无法传递 webhook 负载,例如在连接超时时,Bird 将自动使用相同的批次 ID 重试批次。当您的 lambda 函数运行接近 10 秒的最大往返时间时,这可能会发生,并且是优化消费者函数以减少执行时间的一个原因。
为了处理所有数据处理活动,我建议创建一个单独的 lambda 函数,每当在 S3 桶上创建新文件时执行 - 这样,数据处理会异步于数据传输执行,而且没有由于连接终止导致的数据丢失风险。在后面的部分中我将讨论处理 lambda 函数。
创建一个应用负载均衡器
为了接收 webhook 负载,我们需要提供一个接收负载的终端。我们通过在 AWS 内创建一个应用负载均衡器来实现这一点,方法是导航到 EC2 > 负载均衡器并点击“创建负载均衡器”。系统会提示您选择要创建的负载均衡器类型 - 对于这个项目,我们希望创建一个应用负载均衡器。我们需要使用应用负载均衡器(ALB)建立我们的消费者,因为事件 webhooks 将作为 HTTP 请求发送,而 ALB 用于在 AWS 内路由 HTTP 请求。我们可以实施 HTTP 网关作为替代方案;然而,在本项目中我们选择使用 ALB,因为它比 HTTP 网关更轻量和具有成本效益。需要注意的是,如果您选择使用 HTTP 网关,事件格式可能与 ALB 不同,因此您的 lambda 函数需要相应地处理请求对象。
一旦您的 ALB 创建后,系统将提示您为 ALB 指定一个名称并配置方案和访问/安全设置 - 由于我们计划接收来自外部来源(Bird)的事件数据,我们将希望 ALB 为互联网可访问的。在“监听器和路由”下,ALB 应监听端口 443 上的 HTTPS,我们希望创建一个目标组,该目标组指向我们的 lambda 函数,使我们的 ALB 将传入请求转发到我们上面创建的消费 lambda 函数。您还需要确保安全组有权通过端口 443 接受流量。
为负载均衡器创建一个 DNS 记录
为了让我们更容易使用我们的 ALB 作为终端,我们将创建一个指向我们 ALB 的 DNS 中的 A 记录。为此,我们可以使用 AWS Route 53 服务(或您当前的 DNS 提供商)并为您希望用作您的终端的主机名创建 A 记录(例如 spevents.<your_domain>)。A 记录应被配置为指向我们创建的 ALB。如果您使用 Route 53 管理 DNS 记录,可以启用“别名”并选择 ALB 来直接引用 ALB 实例;否则,如果您使用外部 DNS 提供商,应将 A 记录指向 ALB 实例的公共 IP 地址。
我建议使用诸如 Postman 的工具来测试一切是否已正确配置,再启用您的 Bird webhook。您可以向您的终端发送一个 POST 请求并确认收到响应。如果您的 POST 请求未返回响应,您可能需要仔细检查您的 ALB 是否在正确的端口上监听。
创建一个 Bird Webhook
现在我们准备在 Bird 中创建 webhook 并使用上述 A 记录定义的主机名作为目标终端。要创建 webhook,请登录您的 Bird 账户内的 Webhooks 部分并点击“创建 Webhook”。系统会提示您为您的 webhook 指定一个名称并提供一个目标 URL - 目标应为先前创建的 A 记录的主机名。请注意,目标 URL 可能需要包含“HTTPS://”。
完成后,验证选择了正确的子账户和事件,并按“创建 Webhook”保存您的配置。所有选定事件类型的事件数据现在将流向我们的目标 URL,并由我们的 ALB 消费以进行下游处理。