托管 webhook 目标

本指南介绍如何在 Cloud Run 服务中托管 webhook 目标。

Cloud Functions 与 Cloud Run

Cloud Functions 和 Cloud Run 都提供托管 webhook 目标的理想解决方案。一般而言,Cloud Functions 的设置速度快,适合进行原型设计,并且非常适合数量较少的工作流。Cloud Run 提供更高的灵活性,能够使用并发处理更大的容量。

在以下情况下使用 Cloud Run:

  • 您使用的是 Cloud Functions 不支持的语言或运行时
  • 您想延长请求超时时间(最长 15 分钟)
  • 您需要大容量并且需要并发(每个容器实例 80 个并发请求)

在 Cloud Run 中创建 webhook 目标

使用 Cloud Run,您可以选择任何语言定义 webhook 目标。您只需要创建可接受数据的 HTTP 端点。 通常情况下,这是通过 POST 完成的,例如:

@app.route('/', methods=['POST'])
def index():
    data = request.get_json()

在上例中,网址的索引页面配置为仅接受 POST 请求并期望数据通过 JSON 负载传递。

与 webhook 提供程序集成

大多数提供 HTTP 回调的服务都要求您验证网址所有权。 这通常是通过发送某种类型的令牌、消息或 Secret 并期待有效响应来实现的。您需要从服务提供商那里获得这些请求。使用上面相同的示例,可能如下所示:

def index():
    data = request.get_json()
    return data['challenge']

提供商验证您的所有权后,您还需要在您的端添加授权。

向请求授权

webhook 目标是一个开放的公共网址。大多数服务都会提供令牌或 Secret,以确保传入请求来自已获授权的服务。由于此网址是公共的,因此您无法阻止恶意企图将数据发送到 webhook 目标。但是,使用令牌或 Secret 可确保您只处理来自授权来源的数据。

为了验证请求,您需要将 Secret 副本存储为环境变量或使用某种密钥管理系统。每个请求都应在请求标头或 JSON 负载中包含 Secret 或令牌,并且您必须对其进行检查以确保来源有效。

def index():
    request_secret = request.headers['Secret']
    if request_secret != os.environ['SECRET']:
        return ('Unauthorized', 401)

如果 webhook 提供程序不支持 Secret 或其他身份验证机制,那么任何使用您的 webhook 目标网址的人都可以发送消息。在这种情况下,您的 webhook 实现应该安全地暴露在公共互联网。

响应请求

大多数服务要求您在服务指定的设定时间内响应请求。如果出现错误响应(例如 HTTP 状态代码 4xx 或 5xx),一些 webhooks 会内置重试方法,因此您需要返回成功状态代码 (2xx),以便让服务知道事件已妥善处理。

def index():
    data = request.get_json()
    return ('', 200)

超时

Cloud Run 和 webhook 提供程序都存在超时。两者中的超时较短者适用于您的应用。如果您的数据处理时间超过了 Cloud Run 或 webhook 提供程序指定的时间,您需要使用可异步完成处理的产品,例如 Pub/SubCloud Tasks。这些产品可让您快速传递数据,立即向 webhook 提供程序返回成功响应,并继续处理而无需担心超时。这些也是处理失败和重试的好选择。

常见的 webhook 模式

类型 示例
中继数据 每次调用 webhook 时通过 Firebase 云消息传递发送通知。
存储数据 将数据存储在 BigQuery 中供日后进行分析。
触发操作 在 Dialogflow 上执行操作、在 Twitter 上发布回复,或者在 GitHub 中提交新代码时推送到暂存环境。

后续步骤