Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

多租户 Webhook 投递平台

一个面向 SaaS 和内部平台的可靠 Webhook 基础设施,支持多租户、API Key 鉴权、幂等接收、持久化队列、HMAC 签名、指数退避重试、死信队列、限流和 Prometheus 指标。

解决的问题

业务系统直接同步调用外部 Webhook 时,容易受到目标服务超时、故障和流量波动影响。本项目把“事件接收”和“外部投递”拆成两个独立阶段:

业务系统 -> API 接收并持久化 -> 后台工作器 -> 外部 Webhook

API 只要成功写入数据库即可快速响应,投递失败由工作器异步重试。

核心能力

  • 多租户 API Key 隔离
  • Idempotency-Key 唯一约束
  • SQLite WAL 持久化任务队列
  • 数据库租约,支持多个工作器竞争任务
  • 指数退避和随机抖动
  • 达到重试上限后进入死信状态
  • HMAC-SHA256 请求签名
  • SSRF 防护,默认拒绝私有和保留网络
  • 租户级固定窗口限流
  • 请求体大小限制和超时控制
  • Prometheus 文本指标
  • Docker Compose 分离运行 API 和工作器

详细设计见 架构文档

环境要求

  • Node.js 24+
  • 或 Docker / Docker Compose

项目无第三方运行时依赖,使用 Node.js 内置 HTTP、SQLite 和测试模块。

本地运行

npm test
npm run seed
npm start

另开终端启动工作器:

npm run worker

本地调试私有地址端点时设置:

$env:ALLOW_PRIVATE_TARGETS = "true"

Docker

docker compose up --build

生产环境必须修改 ADMIN_TOKEN,并通过反向代理配置 TLS。

快速使用

1. 创建租户

curl.exe -X POST http://localhost:8788/admin/tenants `
  -H "Authorization: Bearer local-admin-token" `
  -H "Content-Type: application/json" `
  -d '{"name":"订单平台"}'

响应中的 apiKey 只应在创建时展示一次。

2. 创建投递端点

curl.exe -X POST http://localhost:8788/v1/endpoints `
  -H "X-API-Key: whk_xxx" `
  -H "Content-Type: application/json" `
  -d '{"name":"订单回调","targetUrl":"https://example.com/webhooks/orders"}'

响应中的 signingSecret 用于目标服务验签。

3. 发送事件

curl.exe -X POST http://localhost:8788/v1/endpoints/ENDPOINT_ID/events `
  -H "X-API-Key: whk_xxx" `
  -H "Idempotency-Key: order-1001-created" `
  -H "Content-Type: application/json" `
  -d '{"type":"order.created","payload":{"orderId":"1001","amount":19900}}'

重复提交相同幂等键会返回已有事件,不会重复入队。

API

方法 路径 说明
GET /health 健康检查
GET /metrics Prometheus 指标
POST /admin/tenants 创建租户,需要管理员令牌
POST /v1/endpoints 创建端点
GET /v1/endpoints 查询端点
POST /v1/endpoints/:id/events 幂等接收事件
GET /v1/events 查询事件
GET /v1/events/:id 查询事件详情

投递协议

投递请求头:

  • x-webhook-id:事件 ID,目标端可用于消费幂等
  • x-webhook-timestamp:Unix 秒时间戳
  • x-webhook-signaturesha256=<HMAC>

签名原文:

timestamp.rawBody

配置

环境变量 默认值 说明
PORT 8788 API 端口
DATABASE_PATH data/webhook-hub.db SQLite 文件
ADMIN_TOKEN local-admin-token 管理员令牌
WORKER_CONCURRENCY 4 单次领取任务数
WORKER_POLL_MS 500 空闲轮询间隔
WORKER_LEASE_MS 30000 任务租约时间
DELIVERY_TIMEOUT_MS 5000 单次投递超时
RATE_LIMIT_PER_MINUTE 120 每租户每分钟请求数
MAX_PAYLOAD_BYTES 262144 最大请求体
MAX_ATTEMPTS 5 最大投递次数
ALLOW_PRIVATE_TARGETS false 是否允许私有网络目标

验证

npm test
npm run test:load

压测脚本会向本地服务并发写入 500 个事件并输出吞吐结果。

设计取舍

  • 当前版本采用 SQLite,强调零依赖、事务和可演示性,不适合直接承载跨区域大规模生产流量。
  • 交付语义为至少一次,目标服务需要消费幂等。
  • 限流为进程内固定窗口,多副本生产部署应替换为 Redis 或网关限流。
  • 管理员令牌和签名密钥当前存储方式适合演示,生产环境应使用密钥管理服务。

About

支持多租户、幂等接收、重试和死信队列的 Webhook 投递平台

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages