服务端 SDK 概览
服务端 SDK 用于记录业务后端确认的事件,例如订单状态变化、后台任务和第三方回调。当前公开接入文档和下载包提供 Java 与 Go SDK;各语言独立发版,版本以服务端下载页为准。
快速接入
- 从服务端下载页取得对应语言的离线包。
- 使用
endpoint和公开projectKey创建应用级客户端。 - 每次记录事件时,显式提供宿主确认的业务身份,并检查本地接纳结果。
- 在宿主停机时有界关闭客户端,检查未确认事件。
选择目标语言查看接入步骤。默认批量模式使用有界内存队列。需与业务事务保持一致的事件,使用宿主事务 Outbox。
客户端与服务端的区别
| 项目 | 客户端 SDK | 服务端 SDK |
|---|---|---|
| 身份 | 保存当前用户与匿名身份 | 每次调用显式传入,不保存全局“当前用户” |
| 生命周期 | 结合页面、前后台及平台调度 | 应用复用实例,在进程关闭时停止接纳并尝试排空 |
| 队列 | 取决于平台存储与实际后端 | 默认有界内存队列,进程退出可能丢失未确认事件 |
| 接收确认 | 按整批 ACK 处理 | 按相同的整批 ACK 语义处理 |
projectKey 用于项目路由,不承担用户认证。用户、租户及请求上下文来自宿主可信业务状态,详见身份与多租户。
上报方式选择
根据事件的可靠性要求和部署条件选择发送方式。
| 路径 | 适合的事件 | 入口 |
|---|---|---|
| 默认批量投递 | 能够容忍进程退出丢失的分析事件 | 默认批量 |
| 日志交接 | 已有受控 LogAgent 或等效采集器 | 日志交接 |
| 宿主事务 Outbox | 必须与订单、支付等业务事务一起提交的事实 | 宿主事务 Outbox |
同步直发只用于当前调用必须等待单条 ACK 的受控场景。它不进入本地队列,也不在进程退出后补发。
默认批量投递
创建 Client 时不额外指定 Consumer,即使用有界内存队列和后台批量上报。track() 被接纳只表示队列接受了这次调用。构造写在语言上报方式页:
内存队列可随进程退出丢失。FileEventStore 只是单进程本地快照实验,不是事务 Outbox。
普通分析事件建议通过宿主的可选模块接入。启动时按本地配置决定是否初始化;配置校验或初始化失败时,关闭分析模块,记录一次脱敏告警,业务继续启动。请求路径仅调用已创建的 Client。队列拒收时增加指标并继续业务处理;网络、磁盘或外部服务调用应留在独立任务中。多个项目需要不同 Client 时,由宿主限制实例总数并负责关闭。
常用批量配置
普通接入可使用默认值;下表适用于内置 HTTP 发送和默认内存队列。调短间隔可能增加请求数,调大队列会增加内存占用,均不保证送达。
| 用途 | Java Builder | Go Options | 默认值与范围 |
|---|---|---|---|
| 队列最大条数 | maxQueueSize(...) | MaxQueueSize | 1000;正整数 |
| 单批条数及后台唤醒阈值 | batchSize(...) | BatchSize | 100;1–100 |
| 自动发送间隔 | flushIntervalMs(...) | FlushInterval | 5 秒;非负。Java 以毫秒、Go 以 time.Duration 表示 |
| 每次发送流程最大尝试数 | maxAttempts(...) | MaxAttempts | 3;正整数 |
Java 将间隔设为 0 会关闭自动发送;Go 的 FlushInterval: 0 表示采用默认间隔,关闭自动发送使用 DisableAutoFlush: true。显式关闭自动发送后,宿主应在需要时调用有界 flush 或关闭;不要把它用于依赖后台定时发送的常驻服务。其他语言的配置见对应接入指南。
Go 的 MaxQueueSize、BatchSize 和 MaxAttempts 为 0 时也使用相应默认值;负值无效。
自动发送一轮失败后,定时和数量触发进入同一个冷却窗口。首次等待约 1–2 秒,连续失败时退避上限逐步升至 30 秒,合法的 Retry-After 可在上限内延长等待。冷却期间继续按容量接收事件。显式 flush 和关闭时的 最后一次发送由宿主控制,请为这类调用设置时限。
单事件编码上限为 32 KiB,包括 SDK 生成的字段。内置队列同时受条数和 8 MiB 事件字节预算限制, 已领取但尚未确认的事件仍占用容量。达到上限时,普通埋点拒绝新事件,业务可以继续执行。新批次最多 1 MiB,已发送过的批次在重试时保留原事件集合,收到 413 时才按协议拆分。字节预算按编码大小计算, 进程的实际内存占用还受运行时对象、发送缓冲和其他 SDK 实例影响。自定义 Store 需要提供等效的资源边界。
内置 HTTP 默认单次请求等待上限为 Go 15 秒、Java 8 秒,包含重定向和响应读取。其他语言的默认值见对应接入指南。 Java 的总时限由连接和读取设置相加,默认分别为 3 秒和 5 秒。Java 对同一 Transport 只允许一个在途交换; 超时后若底层网络调用仍未退出,该调用继续占用发送名额,重试不会并发追加请求。关闭时仍应单独设置等待预算。
紧急停采停发
宿主可通过本地配置或运维开关调用 SDK 的停止方法,例如 Java 的 client.stop() 或 Go 的 client.Stop()。 调用立即停止新事件准入与后台调度,并取消在途发送;队列保留,之后的显式 flush 或 close 会报告取消。 已开始的磁盘或自定义传输调用可能仍需自行返回,迟到 ACK 不会确认批次。恢复时创建新的 Client; 复用文件队列前,先确认原持有者及其后台操作已退出。
普通发布和停机仍使用有时限的 close。Go 和 Java 的有时限关闭可以先于阻塞的 Store 调用返回; 失败时的未确认数量以最近观测为准。同步 Store 会占用调用它的业务线程。业务请求路径使用默认内存队列;有持久化要求时,将同步存储和网络投递放到独立执行单元。
Java 的 flush(timeoutMs) 同时限制调用方等待。超时后仍在运行的自定义 Transport 或 Store 继续占用该 Client 的发送资格,直到实际退出。同一 ClassLoader 最多八个独立的显式限时 flush 正在执行,满载立即返回错误。
查看投递诊断
使用 Java 的 client.diagnostics() 或 Go 的 client.Diagnostics() 读取队列和累计计数。发生批次发送或 ACK 校验失败后,最近投递失败信息提供低基数失败类别;HTTP 错误还可包含状态码。Java 使用 getLastDeliveryFailure(),其他语言的访问方式见对应 API 文档。
该字段记录最近一次批次发送流程或 ACK 校验失败,即使后续批次成功也不会自动清除;例如 413 拆批后成功仍可能保留父批次的 413。同一批次在内部重试后成功时,中间失败不会写入此字段。请结合队列和计数判断当前情况。诊断不包含响应正文、原始异常、身份或事件属性,也不表示事件已最终入库。
各语言读取最近投递失败
下面的 client 是已初始化的应用级客户端。可在宿主的诊断或监控流程读取;字段不会在读取后清除,不要在每次业务请求中重复输出相同日志。
com.trackbusiness.server.model.DeliveryFailure failure = client.diagnostics().getLastDeliveryFailure();
if (failure != null) {
// 将 failure.getKind()、failure.getStatus() 接入宿主的脱敏监控。
}failure := client.Diagnostics().LastDeliveryFailure
if failure != nil {
// 将 failure.Kind 和 failure.Status 接入宿主的脱敏监控。
// Status 为 0 表示没有 HTTP 状态码。
}排查发送失败时,先看 lastDeliveryFailure、队列大小和拒绝计数,再按状态定位:
- 401 / 403:检查接收地址与项目环境是否匹配、项目是否启用以及所用项目凭据是否有效;需要时请网关运维通过脱敏的批次标识或请求标识查询对应日志。不要在日志或工单中粘贴项目凭据。
- 429 / 5xx:检查网关限流、服务状态和网络;SDK 对这些状态按可重试错误处理,但持续故障仍可能填满内存队列。
- 413:检查事件与批次大小;SDK 会尝试拆分多事件批次,单个事件仍过大时可能被拒绝。
除 408、429 外,不可重试的 4xx 按整批终态拒绝处理;队列减少不等于发送成功。处理异常或恢复业务时应结合宿主保存的事件及接收端记录判断,不能通过诊断快照补回已拒绝事件。
FileEventStore 快照限制
四种语言的 FileEventStore 对序列化快照设置 64 MiB 和 JSON 嵌套深度 64 的保护线。超限写入会拒绝本次准入并保留已提交文件;超限快照恢复会失败关闭,不会按空队列恢复或自动截断。遇到该情况时保留文件并迁移到宿主 Outbox/WAL。该限制不代表进程内存上限或生产吞吐承诺。
日志交接
事件先写成不可变日志,再由经过准入的采集器交给 Collector。磁盘预算、锁、.open / .jsonl 和 Agent 边界见日志交接边界。构造写在语言上报方式页:
宿主事务 Outbox
业务写入和事件记录放在同一数据库事务中,由宿主 Relay 投递。宿主负责事务表与 Relay,不需要额外的 SDK 初始化模式。不要把同一事件再送进默认 track 队列。发送后、终态提交前仍可能崩溃并重投,必须依赖 Collector 幂等。
事务写入、领取、重放与终态提交由宿主实现,并在实际数据库和部署环境验证,包括多实例 Relay 协调和失败重试。具体调用见对应语言的上报方式页。
同步直发
每次调用等待 Collector 的单条 ACK。不进入 Store,也不隐式重试。重试必须复用原来的 eventId。Transport 由宿主提供。构造写在语言上报方式页:
语言指南
各语言独立发版,通过离线包交付。使用下载包对应的版本文档。
四种语言共用操作语义、身份与多租户和日志交接边界。框架生命周期接入见对应语言指南。当前下载包不包含 Servlet、Spring Boot Starter 和 Gin 框架适配模块;可按语言指南使用核心 SDK 接入。
如何理解接纳、flush 和停机结果
服务端 SDK 提供事件接纳、flush 和停机结果。不同语言的取消与等待方式有所区别,应按对应语言指南处理。
| 层次 | 四语言语义 | 不能推导出的保证 |
|---|---|---|
| track 接纳 | 当前 SDK 接受事件进入其 Store/处理通道 | Collector 已接收、业务事务已提交 |
网络 flush 结果 accepted | 对本次实际处理批次收到有效整批 ACK 后累计的数量 | 当前所有历史积压均已排空、报表可查 |
rejected | 本次处理中的明确终态拒收 | 任意超时都属于拒收 |
unresolved、错误或等待超时 | 仍有未确认或无法完整观察的工作 | 确定未送达、可以立即更换 Store owner |
| LoggingConsumer 写入/flush | 交接文件写入或同步结果 | SDK 已收到 Collector ACK |
Java 使用带毫秒预算的 flush/close,Go 使用有 deadline 的 Context;其他语言的调用方式见对应 API 文档。常驻服务复用 Client、保留后台批量发送;短生命周期或任务退出时给出有限等待预算并处理未确认结果,不为每条事件同步等网络。
FileEventStore 是单进程本地持久卷上的快照恢复方案;它不是事务 Outbox/WAL。等待超时不自动转移 Store/文件锁所有权。权威业务事件仍应使用宿主事务 Outbox/WAL,并按各语言停机、Consumer 和恢复合同交接。具体函数签名与不同 Consumer 边界见各语言快速开始。