Skip to content

第 4 篇 · 4.1 动态视角

学习目标

完成本节后,你将能够:

  1. 用同一套模板阅读 tRPC、Public API、ingestion、worker 和 events query。
  2. 区分同步返回路径、异步 job 路径和查询路径。
  3. 判断一次改动应该落在入口层、契约层、执行层还是状态层。

4.1.1 静态架构回答“有什么”,动态架构回答“怎么动”

第 3 篇讲了 webpackages/sharedworker 和状态层。第 4 篇关心的是运行时:

  • 请求从哪个入口进入;
  • 哪个 wrapper 建立 auth 和 tenant scope;
  • 哪个 schema 把外部输入变成内部数据;
  • 是否需要投递队列;
  • worker 消费后如何处理失败;
  • 最终读写哪个存储;
  • 指标和日志在哪里打。

读 Langfuse 的运行链路时,建议按下面的模板做笔记。

维度要问的问题Langfuse 示例
入口谁调用?HTTP、tRPC、BullMQ 还是内部函数?Browser 调 tRPC;SDK 调 Public API;worker 消费 Redis job。
可信边界这里的身份和租户上下文怎么建立?protectedProjectProcedurecreateAuthedProjectAPIRoute、queue payload 的 authCheck.scope.projectId
契约输入输出由什么 schema/type 约束?Zod request/response、QueueJobsFilterState、domain schema。
执行这里做业务逻辑,还是只做协调?ingestion processor 负责协调 S3/Redis/secondary queue,业务 merge 在 IngestionService
状态读写 Postgres、ClickHouse、Redis 还是 S3?raw event 进 S3,job 进 Redis,最终 record 进 ClickHouse。
失败失败后是同步返回、重试、降级还是记录指标?API 返回统一错误;BullMQ retry;S3 SlowDown 进入 secondary queue;writer 记录 rows_dropped。

4.1.2 五条主链路总图

这张图里有三种箭头:

  1. 同步请求箭头:UI/tRPC/Public API 需要给调用者返回结果。
  2. 异步数据箭头:ingestion 接收后把重工作交给 queue + worker。
  3. 查询箭头:UI filter 最终 lower 成 ClickHouse SQL。

4.1.3 五条链路分别学什么

链路核心问题你会学到的设计点
tRPCUI 内部请求怎么获得 project scopeprocedure 工厂、session、membership、OpenTelemetry、feature flag gate。
Public API外部 REST 契约怎么稳定middleware、API key access level、rate limit、Zod response、Fern。
Ingestion高频事件为什么不直接写 ClickHouseS3 raw event、轻量 job、producer/consumer path contract、sampling。
Worker queue后台任务如何统一执行WorkerManager、BullMQ options、wait/processing metrics、failed/error/stalled。
v4 events query宽事件表怎么高效查询events_core/events_full、field set、FilterState lowering、split query。

4.1.4 一条链路的“源码读法”

以 Public API POST /api/public/traces 为例,不要只看 route 文件。按顺序看:

  1. web/src/pages/api/public/traces/index.ts:这个 endpoint 暴露什么 HTTP 方法。
  2. withMiddlewares.ts:CORS、method dispatch、error boundary、ClickHouse route tag。
  3. createAuthedProjectAPIRoute.ts:API key、access level、rate limit、query/body/response schema。
  4. web/src/features/public-api/types/**:外部请求/响应契约。
  5. processEventBatch.ts:如果是写入事件,它如何进入 ingestion 数据面。
  6. queues.ts:异步 job 载荷是不是跨部署兼容。
  7. worker/src/queues/ingestionQueue.ts:consumer 如何读取 job 并处理失败。

同样的套路可以套到任何链路。

4.1.5 初学者最容易误读的地方

误读正确理解
web 就是前端web 同时包含 Next.js UI、tRPC、Public API、ingestion HTTP 入口。
shared 是 utilsshared 是跨运行时契约中心,尤其是 queue/schema/filter/query。
worker 只是在跑 jobworker 还统一处理 metrics、error、stalled、secondary queue、ClickHouse writer。
Redis 保存事件Redis 保存 job 和短期缓存;raw event 在 S3/blob。
ClickHouse 只有一张 events 表v4 读写围绕 events_fullevents_core,legacy 表还在迁移期共存。
FilterState 是 UI 状态FilterState 是 UI、API、query builder 共享的过滤语言。

4.1.6 本篇阅读顺序

建议按顺序读:

  1. tRPC 链路:理解 UI 内部 API 的 procedure 工厂和 project scope。
  2. Public API 链路:理解外部契约、API key、限流和 Fern。
  3. Ingestion 链路:理解高吞吐写入为什么拆成 S3 + queue + worker + ClickHouse。
  4. Worker 队列:理解后台执行器、重试、指标和隔离。
  5. v4 Events 查询:理解 FilterState 如何变成高性能 ClickHouse 查询。