TL;DR:Webhook 是一种事件驱动的 HTTP 回调机制——当某个事件发生时(如支付完成、代码提交),服务端主动向你配置的 URL 发送一条 POST 请求,而不是等你去查询。
1. 一句话定义
Webhook = “事件发生时,自动打给你的电话”
传统 API 是你主动打电话去问(轮询),Webhook 是对方有事情主动打给你(推送)。
2. Webhook 工作原理(图解)
2.1 一次完整的 Webhook 流程
sequenceDiagram
participant U as 用户
participant S as 服务端<br/>(Stripe/GitHub)
participant C as 你的服务器<br/>(回调 URL)
U->>S: 完成支付 / 提交代码
Note over S: 事件触发
S->>C: POST /webhook/payment<br/>Payload: {event, data}
C->>C: 验证签名 → 处理业务
C-->>S: HTTP 200 OK
Note over S: 标记投递成功
流程拆解:
| 步骤 | 动作 | 说明 |
|---|---|---|
| ① | 事件触发 | 用户在 Stripe 支付成功 / 在 GitHub push 代码 |
| ② | 服务端组装 Payload | 生成 JSON 格式的事件数据 |
| ③ | 向回调 URL 发送 POST | 携带签名 Header,确保来源可信 |
| ④ | 你的服务器处理 | 验证签名 → 执行业务逻辑 |
| ⑤ | 返回 2xx 状态码 | 告诉服务端"我已收到" |
2.2 技术本质
Webhook 在技术层面就是一条普通的 HTTP POST 请求,但它有 3 个核心特征:
| 特征 | 说明 | 为什么重要 |
|---|---|---|
| 事件驱动 | 由服务端事件触发,非客户端请求 | 实时性高,无需轮询消耗资源 |
| 回调地址 | 用户预先注册一个 URL | 服务端知道"往哪里推" |
| 单向推送 | 服务端 → 客户端,一般不回传数据 | 简单直接,但有状态管理需求 |
3. Webhook vs API 轮询:核心区别
| 对比维度 | API 轮询 (Polling) | Webhook (推送) |
|---|---|---|
| 通信方向 | 客户端 → 服务端(Pull) | 服务端 → 客户端(Push) |
| 实时性 | 取决于轮询间隔(秒/分钟级) | 事件触发即推送(毫秒级) |
| 资源消耗 | 高(反复请求,大量空响应) | 低(仅在事件发生时通信) |
| 服务端压力 | 大(需处理大量查询请求) | 小(仅在事件时推送) |
| 实现复杂度 | 简单(定时发请求即可) | 较高(需回调接口 + 签名验证) |
| 可靠性 | 简单可控 | 需处理失败、重试、幂等 |
| 适用场景 | 低频查询、数据量小 | 实时通知、事件驱动 |
一句话总结:
- 需要实时知道发生了什么 → 用 Webhook
- 只是偶尔查一下状态 → 用 API 轮询
4. 真实场景示例
4.1 Stripe 支付通知
当用户完成一笔支付,Stripe 向你的服务器推送事件:
POST https://your-app.com/webhooks/stripe
Content-Type: application/json
Stripe-Signature: t=1234567890,v1=abcdef123...
{
"id": "evt_123456",
"object": "event",
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_123456",
"amount": 2000,
"currency": "usd",
"status": "succeeded"
}
}
}
你的服务器做什么?
- 验证
Stripe-Signature签名 - 根据
type判断事件类型 - 更新订单状态为"已支付"
- 返回
200 OK
4.2 GitHub 代码推送
当你 push 代码到仓库,GitHub 自动化部署:
POST https://your-ci.com/webhooks/github
X-GitHub-Event: push
X-Hub-Signature-256: sha256=abc123...
{
"ref": "refs/heads/main",
"repository": {
"full_name": "your-org/your-repo"
},
"commits": [...]
}
你的 CI 服务器做什么?
- 验证签名
- 检查
ref是否为main分支 - 拉取代码 → 构建 → 部署
4.3 飞书审批通知
员工提交请假审批,飞书向 HR 系统推送:
POST https://hr-system.com/webhooks/feishu
{
"event_type": "approval_task",
"instance_code": "ABC123",
"status": "pending",
"applicant": {
"name": "张三",
"department": "技术部"
}
}
5. Webhook 的核心组成
一条标准的 Webhook 请求包含这些要素:
| 组成 | 典型值 | 作用 |
|---|---|---|
| HTTP 方法 | POST | 推送数据的标准方法 |
| Content-Type | application/json | 数据格式声明 |
| 回调 URL | https://api.yoursite.com/webhooks | 你注册给服务端的接收地址 |
| Payload | JSON 事件数据 | 事件的详细信息 |
| 签名 Header | X-Signature / Stripe-Signature | 验证请求未被篡改 |
| 事件类型 | payment.success / push | 区分不同业务事件 |
6. 本地调试 Webhook(新手必看)
Webhook 需要一个公网可访问的 URL,但开发时服务一般在本地。解决方法:
方法一:ngrok(最简单)
# 安装 ngrok
brew install ngrok
# 将本地 8080 端口暴露为公网 URL
ngrok http 8080
# 你会得到一个类似 https://abc123.ngrok.io 的 URL
# 把这个 URL 配置到 Stripe/GitHub 作为回调地址
方法二:Cloudflare Tunnel
# 安装 cloudflared
brew install cloudflared
# 创建隧道
cloudflared tunnel --url http://localhost:8080
方法三:RequestBin(不运行本地服务)
如果你只是想看看 Webhook 长什么样,用 webhook.site:
- 打开网站,获得一个随机 URL
- 把这个 URL 配置到 Stripe/GitHub
- 页面实时显示收到的请求
7. Webhook 的优缺点
✅ 优点
- 实时性强:事件触发后立即推送,无需等待轮询周期
- 资源效率高:只在有事件时通信,省去大量空请求
- 系统解耦:事件发送方和消费方互不依赖
- 扩展性好:一个事件可推送至多个消费者
❌ 缺点
- 回调地址必须公网可访问:本地调试需要额外工具
- 可靠性需自行保障:网络故障、服务端宕机会导致推送失败
- 安全风险:暴露的 URL 可能被恶意调用,必须验证签名
- 幂等性处理:同一事件可能因重试被多次推送
8. 常见误区
| 误区 | 真相 |
|---|---|
| “Webhook 是新技术” | Webhook 2007 年就由 Flickr 提出,是成熟标准机制 |
| “Webhook 和 API 一样” | API 是 Pull,Webhook 是 Push,本质不同 |
| “返回 200 就行了” | 生产环境还需验证签名、处理重试、保证幂等 |
| “Webhook 一定比轮询好” | 低频查询场景用轮询更简单可靠 |
| “Webhook 可以替换消息队列” | Webhook 是通知机制,MQ 是存储+投递系统,互补关系 |
9. FAQ
Q1: Webhook 和消息队列(如 Kafka)有什么区别?
Webhook 是**“点对点通知”——服务端直接推给你的服务器。消息队列是“中间件存储”**——事件先存到队列,消费者按需拉取。Webhook 更简单直接,但缺乏持久化;队列更可靠,但架构更复杂。生产环境常将两者结合:Webhook 作为入口,队列作为缓冲层。
Q2: 如果我的服务宕机了,Webhook 会丢失吗?
取决于服务端的实现。专业的 Webhook 平台(如 Stripe)会:
- 首次推送失败 → 进入重试队列
- 按指数退避重试(立刻 → 1分钟后 → 5分钟后 → …)
- 多次失败后可能标记为死信
自建 Webhook 时,你也应该实现类似的重试逻辑。详见重试与幂等性设计。
Q3: Webhook 可以支持 GET 请求吗?
理论上可以,但强烈不推荐。GET 请求有长度限制、不应携带请求体、会被浏览器缓存。Webhook 的标准做法是使用 POST + JSON。
Q4: 我需要为每个事件类型配置不同的 URL 吗?
不一定。常见的做法:
- 单 URL + 事件类型字段:一个回调地址,Payload 中用
event_type区分 - 多 URL:不同事件配置不同回调(灵活性高,但管理复杂)
Q5: Webhook 有数据大小限制吗?
有,取决于具体平台和你的服务器配置:
- 一般来说 Payload < 1MB 比较安全
- Stripe 的限制约几十 KB
- 大文件推荐:Webhook 推送"事件通知" → 你的服务器再用 API 拉取完整数据
Q6: 开发时怎么测试 Webhook?
推荐顺序:
- 用 webhook.site 观察原始请求
- 用 ngrok 暴露本地服务调试
- 用平台提供的 Test Webhook / Mock 功能
- 查看平台的事件日志确认投递状态
10. 下一步
理解了 Webhook 是什么,接下来你可以深入了解:
- Webhook vs 轮询 vs WebSocket — 三种实时通信方案的完整对比
- Webhook 安全最佳实践 — HMAC 签名、IP 白名单、TLS 加密的代码实现
- Webhook 调试完全指南 — ngrok、日志分析、常见问题排查
- Stripe Webhook 集成实战 — 完整可运行的代码示例
- Webhook Gateway 设计 — 统一接收入口与事件路由分发
- Webhook 监控告警体系 — Metrics + Logs + Tracing
11. 核心要点回顾
Webhook = 事件驱动 + HTTP POST + 回调 URL
三大核心特征:
① 服务端主动推送(Push)
② 用户预先注册回调地址
③ 携带签名保证安全
vs API 轮询:实时性更好、资源消耗更低、实现更复杂
生产必备:签名验证 + 重试机制 + 幂等处理
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。