908 words
5 minutes
Webhook 工作原理

Webhook 工作原理#

本质#

Webhook 就是一个 HTTP 回调:当 A 系统发生某件事时,A 主动发一个 HTTP POST 请求到 B 系统预先注册的 URL。

工作流程#

B 系统注册回调 URL ──→ A 系统保存这个 URL
A 系统事件触发 ──→ HTTP POST ──→ B 系统接收处理
(代码推送/支付完成等) (携带事件数据JSON)
  1. 注册:你告诉 GitHub “当代码推送时,POST 到 https://ci.example.com/build
  2. 触发:有人 git push
  3. 推送:GitHub 向你的 URL 发送 POST,body 里是推送详情(JSON)
  4. 处理:你的 CI 服务器收到请求,开始构建

对比传统 API#

传统 APIWebhook
模式拉取(polling)推送(push)
谁主动客户端反复请求服务端主动通知
实时性取决于轮询频率事件即触发
资源消耗大量无效请求只有事件时才发请求

典型场景#

  • GitHub → 代码推送后通知 CI/CD 构建
  • 支付平台 → 交易完成后通知商户系统
  • Slack/钉钉 → 机器人收到消息后触发自动化
  • Kubernetes → Admission Webhook 拦截和校验请求

关键细节#

  • 幂等性:网络可能重传,接收方需要保证同一事件处理多次结果一致
  • 签名验证:发送方通常用 HMAC 签名,接收方验证请求确实来自声称的源
  • 重试机制:发送方在收到非 2xx 响应时,会按指数退避重试

本质上就是 发布-订阅模式的 HTTP 实现,把”订阅”简化为”注册一个 URL”。


服务端如何感知变化并推送#

以 GitHub Webhook 为例,看完整链路。

注册阶段#

你在 GitHub 仓库设置里填入:

  • 回调 URL:https://ci.example.com/build
  • 触发事件:push
  • Secret:my_secret_key

GitHub 把这些存到数据库。

事件触发#

有人执行 git push,GitHub 收到代码后:

git push 到 GitHub
GitHub 处理完推送逻辑
GitHub 查数据库:哪些 Webhook 订阅了 push 事件?
找到你的回调 URL
构造 HTTP POST 请求,body 是事件数据 (JSON)
用 Secret 计算 HMAC 签名,放在 Header 里
发送 POST https://ci.example.com/build

关键点:这里没有魔法,GitHub 的代码里就是硬编码了”完成 push 操作后,查 webhook 表,逐个发 HTTP 请求”。本质上是一个函数调用后触发的副作用

# GitHub 内部伪代码
def handle_git_push(repo, commits):
# 1. 正常处理推送
save_commits(repo, commits)
update_refs(repo)
# 2. 查询订阅了这个事件的 webhook
webhooks = db.query("SELECT * FROM webhooks WHERE repo=? AND event='push'", repo)
# 3. 逐个推送
for hook in webhooks:
payload = {"commits": commits, "repo": repo}
signature = hmac_sign(payload, hook.secret)
http_post(hook.url, payload, headers={"X-Hub-Signature": signature})

接收端处理#

你的 CI 服务器收到请求后:

# 你的服务器伪代码
@app.post("/build")
def on_push(request):
# 1. 验证签名,确认是 GitHub 发的
verify_signature(request.body, request.headers["X-Hub-Signature"])
# 2. 解析事件数据
data = json.loads(request.body)
# 3. 执行业务逻辑
trigger_build(data["repo"], data["commits"])
# 4. 返回 200,告诉 GitHub "收到了"
return Response(status=200)

“HTTP 回调”是什么意思#

回调这个概念来自编程:

# 编程里的回调
def do_something(callback):
result = work()
callback(result) # 干完后调用你传进来的函数
do_something(my_handler) # 把 my_handler 作为回调传进去

HTTP 回调就是把同样的思路搬到网络层面:

编程回调:把函数指针传过去,事件发生时调用你的函数
HTTP 回调:把 URL 传过去,事件发生时向你的 URL 发 HTTP 请求
  • “回调 URL” = 你告诉对方”有事打这个电话”
  • “HTTP 回调” = 对方通过 HTTP 请求”打这个电话”

Webhook 就是 HTTP 层面的回调函数,URL 就是指针,POST 请求就是函数调用。

Webhook 工作原理
https://sgjki547.top/posts/webhook-工作原理/
Author
SGJki
Published at
2026-05-31
License
CC BY-NC-SA 4.0