Webhook 是什么
Webhook 是反向集成方式:服务方在事件发生时主动向订阅方预先登记的地址发起 HTTP 回调,订阅方收到后立即处理或入队。它把「轮询查询变化」变成「事件推送」,实时性与成本都更优,但可靠性责任被分散到两方:发送方要做签名、重试、退订与背压控制,接收方要做验签、去重与快速响应。双方对投递语义(通常是至少一次)达成一致,是这套机制能用的前提。
基本信息
| 方向 | 服务方 → 订阅方的 HTTP POST 回调 |
|---|---|
| 投递语义 | 通常为至少一次,接收方必须实现幂等 |
| 签名 | HMAC 签名 + 时间戳,接收方校验防伪造与重放 |
| 重试 | 指数退避重试若干次,失败事件可查询或补发 |
| 订阅治理 | 端点验证、停用、审计与配额,避免恶意地址被反复调用 |
典型使用场景
- 支付结果通知:支付网关回调商户系统,商户据此更新订单状态
- 代码与流水线事件:仓库推送、合并请求等事件触发自动化流程
- 工单与审批状态:状态变化推送订阅方,减少轮询查询
- 消息与通知:第三方平台推送用户消息或撤销事件
- 数据同步:源系统变更后通知下游增量拉取或直接携带变更内容
- 风控告警:规则命中时实时推送到安全平台
接收方校验要点(伪代码)
接收方校验要点(伪代码)
# 1 验签:用共享密钥对「时间戳 + 请求体」做 HMAC,比较结果
sign = HMAC_SHA256(secret, timestamp + '.' + raw_body)
if not verify(sign, header.signature): reject # 防伪造
# 2 防重放:时间戳超出窗口直接拒绝
if now - timestamp > 300s: reject
# 3 幂等:按事件 ID 去重,已处理过直接返回成功
if event_id in processed_set: return 200
# 4 快速响应:校验通过后立即入队,重活异步处理,避免发送方超时重试
# 5 顺序:同一业务键的事件按时间戳排序处理,乱序时等待或丢弃后重拉双方职责划分
| 事项 | 发送方职责 | 接收方职责 |
|---|---|---|
| 签名 | 用共享密钥签名并带时间戳 | 校验签名与时间窗口 |
| 重试 | 指数退避重试并记录投递结果 | 快速响应,不因处理慢而超时 |
| 去重 | 保证事件 ID 稳定不变 | 按事件 ID 幂等处理 |
| 失败可见 | 提供投递日志与手动补发入口 | 配置告警,处理失败时主动排查 |
| 停用 | 多次失败后自动停用并通知 | 修复端点后主动申请恢复 |
回调不可靠是常态:把「至少一次」写进对接文档并要求接收方幂等,比承诺「一定成功」更实际;发送方也应提供按时间范围补拉的兜底接口。
接收端点要在数百毫秒内返回:先落库或入队再处理,长耗时逻辑放到异步任务,否则发送方超时重试会让同一条事件多次到达。