跳转到内容
类型解锁
阶段生产环境
难度中等
工作分享流
用于后端开发者
用于开发团队
服务管道
服务Exec
为何选 HoodyHTTP 原生
为何选 Hoody默认多人协作
类型解锁
阶段生产环境
难度中等
工作分享流
用于后端开发者
用于开发团队
服务管道
服务Exec
为何选 HoodyHTTP 原生
为何选 Hoody默认多人协作
类型解锁
阶段生产环境
难度中等
工作分享流
用于后端开发者
用于开发团队
服务管道
服务Exec
为何选 HoodyHTTP 原生
为何选 Hoody默认多人协作
类型解锁
阶段生产环境
难度中等
工作分享流
用于后端开发者
用于开发团队
服务管道
服务Exec
为何选 HoodyHTTP 原生
为何选 Hoody默认多人协作
PIPE · HTTP 扇出

你无需自建的 webhook 扇出

Stripe 用 ?n=12 把事件主体 POST 到一个 pipe 路径。十二个订阅者用 ?n=12 GET 同一个路径。pipe 在所有人连接好之前一直保留消息,然后一次性向全部十二个推流。没有 broker,没有 consumer group,没有 DLQ。

阅读 pipe 文档

一个 URL。十二个读者。每条连接独立背压。

Hoody Pipe 是带多接收方模式的 HTTP 流。在发送方和接收方 URL 上都追加 ?n=N,pipe 会等到 N 个读者都接入后,再把主体同时镜像给所有人。慢的那些只压自己的连接——快的那些继续流。

01STEP 01 · 接入

Stripe POST 到 pipe

你的 Stripe 端点把事件主体直接转发到 /api/v1/pipe/billing?n=12。连接在 pipe 等待十二个接收方集合期间被阻塞。

02STEP 02 · 集合

十二个订阅者接入

每个订阅者都是容器中的一个 curl 循环,用 ?n=12 GET 同一个路径。pipe 把主体保留在内存中,直到第十二个读者连接——没有磁盘上的队列,没有要刷盘的内容。

03STEP 03 · 推流

扇出,然后忘掉

所有人连接好后,主体一次性流向全部十二个。慢读者把背压施加在自己的套接字上;其他人继续走。最后一个读者断开时,pipe 忘掉这条消息。

stripe-webhook.sh
# Sender side — your Stripe webhook handler.
# Pipe holds the body until 12 readers are attached.
curl -X POST "https://api.hoody.com/api/v1/pipe/billing?n=12" \
  -H "Authorization: Bearer $HOODY_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary "@stripe-event.json"

# Receiver side — one of twelve subscriber containers.
# Same path, same n. Streams the event body when fan-out is ready.
curl -N "https://api.hoody.com/api/v1/pipe/billing?n=12" \
  -H "Authorization: Bearer $HOODY_TOKEN" | ./billing-handler.sh

# n must match on both ends — mismatch returns 400.
# Default n=1 is point-to-point. n=12 is fan-out for twelve.

两端用同一个 URL、同一个查询字符串。发送方的连接就是 broker;读者的连接就是 consumer group。背压是按套接字计的,而不是按主题——因为根本没有主题,只有一份在传输的主体和十二个套接字在拉它。

订阅者像进程一样来去

增加一个订阅者就是再起一个容器里多跑一条 curl。移除一个就是杀掉那条 curl。没有 broker 配置,没有 consumer-group 再均衡,没有 DLQ 要清空——集群拓扑就是此刻碰巧在跑的那些进程。

subscribers diff · 最近 5 分钟无需再均衡
  • + 新增
    WHKAUD
    起了两个新容器
  • − 移除
    MIX
    容器被杀,curl 退出
  • = 不变
    BILANLLOGFRDSUCSLACRMCDNNOT
    仍在同一条 n=12 路径上

pipe 不追踪谁订阅了。它只是为每个事件等 n 个连接。两端把 n 调高,下个事件就等新的人头数。没有要被破坏的成员状态,因为根本没有成员关系。

你不再需要运营什么

下面每一行都是当协议本身就是 broker 时消失的一类工作。无需配置基础设施,无需学抽象——只有 curl 和 ?n。

  • 无需配置队列

    没有 SQS,没有 Kafka 集群,没有 RabbitMQ exchange。pipe 就是队列,而它一次只为一条消息存活。

  • 无需 consumer-group 簿记

    没有 offset、没有 commit、没有再均衡。pipe 把主体保留到 n 个套接字接入——这就是全部协调模型。

  • 无需 DLQ 清空

    如果发送方在 n 个读者就绪前断开,pipe 会超时(5 分钟 TTL),Stripe 会重试。没有要照看的毒消息桶。

  • 无需逐语言 SDK

    订阅者是 curl 循环。发送方是 curl。协议是 HTTP。任何能命中 URL 的东西都能加入这个集群。

  • 按套接字背压

    慢读者只压自己的连接。其他十一个继续以全速推流。整个机群没有头部阻塞。

  • 默认遗忘

    最后一个读者断开的瞬间,主体就消失了。无需设保留策略,无需排日志压缩,无需写 GDPR 删除请求作业。

十二个订阅者,一个 URL,没有 broker。

下面这些 broker,是在 HTTP 扇出还不是一个查询参数之前你必须装的东西。右侧是替代它们的——一个路径、一个 n、十二个互不知道彼此组成集群的 curl 进程。

你不用再跑的东西
  • AWS Lambda + SQS/SNS
  • Apache Kafka
  • RabbitMQ exchanges
  • 自定义 webhook 路由器
你改成调用什么
POST /api/v1/pipe/billing?n=12

十二个接收方用同一个 n GET 同一个路径。pipe 就是 broker——并在最后一个读者挂断的瞬间忘掉这条消息。

阅读扇出章节

这取代了什么

如果你为了把一个 webhook 广播给 N 个消费者去抓下面任何一个,pipe 模型用两次 curl 调用就能干同样的活——一边是发送方,另一边是接收方。

  • AWS Lambda + SQS/SNS每个主题一个 broker,每个订阅者一份 IAM
  • Apache Kafka集群、ZooKeeper/KRaft、consumer group
  • RabbitMQ exchangesbinding、vhost、每环境一个管理 UI
  • 自定义 webhook 路由器一个要维护的服务,一套要发明的重试
  • Pub/Sub 服务按消息计费,GCP/AWS 锁定
  • HTTP 扇出插件每套技术栈一个网关插件,无背压

你以前要花一个 sprint 才能写出的扇出,现在是一个查询参数。追加 ?n=12 然后发布。

阅读 pipe 文档

阅读其他内容