Rivet API 数据模型解析:DatacenterHealth 与数据中心健康度探测(Fanout)
2026/9/18 3:22:58 网站建设 项目流程

Rivet API 数据模型解析:DatacenterHealth 与数据中心健康度探测(Fanout)

【免费下载链接】actorsRivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.项目地址: https://gitcode.com/GitHub_Trending/riv/actors

本篇技术指南以 Rivet 开源仓库中 DatacenterHealth 模型文档 为核心,完整讲解该模型的字段结构、序列化规则,以及它背后的GET /health/fanout健康度探测接口的实现原理。读完本文,你将掌握 Rivet 多数据中心场景下健康状态的数据组织方式,能够正确解析各 SDK 中返回的 DatacenterHealth 数据,并理解服务端是如何并发探测各数据中心并汇总结果的。

一、模型定位:一次健康探测的“单数据中心结果”

在 Rivet 的公开 API(rivet-api-public)中,DatacenterHealth并不是一个独立接口的返回体,而是GET /health/fanout接口返回的 HealthFanoutResponse 中datacenters数组的单个元素类型。它的职责是描述"对某一个具体数据中心的健康检查结果",包括该数据中心的标识、健康状态、往返延迟(RTT)以及可选的详细响应或错误信息。

从服务端源码看,该结构在 engine/packages/api-public/src/health.rs 中定义如下:

#[derive(Debug, Serialize, Deserialize, ToSchema)] pub struct DatacenterHealth { pub datacenter_label: u16, pub datacenter_name: String, pub status: HealthStatus, pub rtt_ms: Option<f64>, pub response: Option<HealthResponse>, pub error: Option<String>, }

它被嵌套在FanoutResponse(对外即HealthFanoutResponse)中:

pub struct FanoutResponse { pub datacenters: Vec<DatacenterHealth>, }

也就是说,一次/health/fanout调用会返回所有已配置数据中心的健康状态数组,而数组中的每一项就是一个DatacenterHealth实例。

二、字段完整说明

下表完整继承了 DatacenterHealth.md 中的属性定义:

字段名类型说明是否必填
datacenter_labeli32(Rust SDK 为 i32,服务端内部为 u16)数据中心标签,用于唯一标识某个数据中心必填
datacenter_nameString数据中心名称必填
errorOption<String>探测失败时的错误信息可选
responseOption<HealthResponse>成功时的健康响应详情可选
rtt_msOption<f64>探测往返时延,单位毫秒可选
statusHealthStatus健康状态枚举必填

字段间存在明显的组合关系,可以归纳为两种结果形态:

  • 成功形态status = Ok,同时携带response(健康响应详情)与rtt_ms(往返时延),errorNone
  • 失败形态status = Error,同时携带error(错误描述)与rtt_msresponseNone

需要特别指出的是,无论成功还是失败,rtt_ms都会被填充(见下文源码分析),它代表这次探测实际消耗的时间,因此不能仅凭rtt_ms是否存在来判断健康状态,必须以status字段为准。

2.1 关联类型:HealthStatus

status字段的类型是 HealthStatus 枚举,序列化值如下:

枚举变体序列化值
Okok
Errorerror

对应服务端定义(health.rs)使用了#[serde(rename_all = "snake_case")],因此 JSON 传输中为小写字符串"ok"/"error"

2.2 关联类型:HealthResponse

成功时的response字段类型为 HealthResponse,包含三个必填字符串字段:

字段名类型说明
runtimeString运行时标识
statusString状态描述
versionString版本号

在服务端源码中,本地数据中心探测会直接构造该响应,runtime固定为"engine"status固定为"ok"version取编译时的CARGO_PKG_VERSION(见 health.rs)。

三、SDK 中的序列化细节:Rust / TypeScript / Go

DatacenterHealth模型在多个官方 SDK 中均有对应实现,理解各语言的命名与序列化映射有助于跨语言联调。

3.1 Rust SDK

Rust 版本实现位于 engine/sdks/rust/api-full/rust/src/models/datacenter_health.rs,由 OpenAPI Generator 生成,特点如下:

  • 所有字段使用#[serde(rename = "...")]显式声明 JSON 字段名为snake_case
  • 三个可选字段(errorresponsertt_ms)使用serde_with::rust::double_option包裹,并配合skip_serializing_if = "Option::is_none",可区分"字段缺失"与"显式 null"两种语义;
  • 提供了便捷构造函数new(datacenter_label, datacenter_name, status),可选字段默认置为None(见 datacenter_health.rs)。

一个典型的 Rust 使用示例:

use rivet_api_public::models::{DatacenterHealth, HealthStatus}; // 构造 let health = DatacenterHealth::new(1, "us-east".to_string(), HealthStatus::Ok); // 反序列化(JSON 字段为 snake_case) let json = r#"{ "datacenter_label": 1, "datacenter_name": "us-east", "status": "ok", "rtt_ms": 12.5, "response": { "runtime": "engine", "status": "ok", "version": "2.3.14" } }"#; let parsed: DatacenterHealth = serde_json::from_str(json).expect("parse");

3.2 TypeScript SDK

TypeScript 版本位于 engine/sdks/typescript/api-full/src/api/types/DatacenterHealth.ts,接口字段采用camelCase命名(datacenterLabeldatacenterNamerttMs),而序列化层 engine/sdks/typescript/api-full/src/serialization/types/DatacenterHealth.ts 通过core.serialization.property("rtt_ms", ...)将 camelCase 字段映射回 wire 格式的 snake_case,保证与 HTTP JSON 报文一致。

3.3 Go SDK

Go 版本位于 engine/sdks/go/api-full/types.go,字段同样以 snake_case JSON tag 暴露,与 Rust / TypeScript 的传输格式保持一致。

所有 SDK 的 schema 定义最终统一来源于 engine/artifacts/openapi.json(DatacenterHealth组件位于其中),这保证了跨语言的一致性。

四、服务端实现:/health/fanout 如何工作

理解字段含义之后,再来看服务端是如何产生这些数据的。核心逻辑位于 engine/packages/api-public/src/health.rs 的fanout/fanout_inner

  1. 鉴权fanout_inner首先调用ctx.auth().await?,要求调用方具备数据中心读取权限(该接口在 OpenAPI 中声明了bearer_auth安全方案,见 HealthApi.md)。
  2. 枚举数据中心:从ctx.config().topology().datacenters读取全部已配置的数据中心,逐个发起探测。
  3. 本地数据中心直查:如果某个数据中心的datacenter_label等于当前进程所属数据中心标签(ctx.config().dc_label()),则不走网络请求,直接本地构造HealthResponse,状态固定为Ok
  4. 远程数据中心 HTTP 探测:对远程数据中心,通过send_health_checks并发发起两个 HTTP GET 请求(详见下文)。
  5. 并发扇出:使用buffer_unordered(16)将全部数据中心的探测任务并发执行,最多同时进行 16 个,全部完成后汇总为Vec<DatacenterHealth>返回。

4.1 远程探测的细节

send_health_checks(health.rs)对每个远程数据中心同时发起两个健康检查:

  • {peer_url}/health:对等节点(peer)的健康端点;
  • {proxy_url}/health:代理(proxy)的健康端点。

两个请求通过tokio::try_join!并发执行,各自带5 秒超时timeout(Duration::from_secs(5)))。判定逻辑为:

  • peer检查必须成功(非 2xx 即判定失败并bail!);
  • proxy检查成功后,将其 JSON 响应解析为HealthResponse作为最终结果。

失败时,错误信息被记录到tracing::warn!日志,并写入DatacenterHealth.error字段,status置为Error

4.2 RTT 的度量方式

无论本地还是远程,每个数据中心的探测任务都会在开始时记录Instant::now()(health.rs),完成后用start.elapsed().as_secs_f64() * 1000.0计算毫秒级时延写入rtt_ms。因此rtt_ms反映的是包含网络往返在内的整体探测耗时,可用于评估各数据中心的链路质量。

五、调用方式与返回示例

health_fanout接口定义见 HealthApi.md:

  • HTTP 方法GET
  • 路径/health/fanout
  • 参数:无
  • 鉴权:Bearer Token(bearer_auth
  • Acceptapplication/json
  • 返回类型:HealthFanoutResponse

一次典型的响应报文如下:

{ "datacenters": [ { "datacenter_label": 0, "datacenter_name": "local-dc", "status": "ok", "rtt_ms": 0.023, "response": { "runtime": "engine", "status": "ok", "version": "2.3.14" } }, { "datacenter_label": 1, "datacenter_name": "remote-dc-a", "status": "error", "rtt_ms": 5120.4, "error": "Proxy health check returned status: 503" } ] }

上例中第一个元素对应本地数据中心(时延极低、直接本地构造),第二个元素对应远程数据中心探测失败(status = errorrtt_ms接近 5 秒超时上限,responsenull)。这也印证了前文的字段组合规律:成功看response,失败看error,时延始终在rtt_ms

六、实用要点小结

  • DatacenterHealth/health/fanout返回数组中"单个数据中心"的健康快照,必须与 HealthFanoutResponse 配合使用。
  • 判断健康与否只能看statusok/error),不要依赖responseerror是否存在来推断。
  • rtt_ms成功失败都会返回,接近 5 秒通常意味着远程探测超时。
  • 各 SDK 的 JSON 传输格式统一为snake_case;TypeScript 接口层使用 camelCase,序列化层负责映射。
  • 服务端通过buffer_unordered(16)并发探测全部数据中心,本地直查、远程走 peer/proxy 双端点(各 5 秒超时),实现细节可继续阅读 engine/packages/api-public/src/health.rs 及 OpenAPI 定义 中的DatacenterHealth组件。

【免费下载链接】actorsRivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.项目地址: https://gitcode.com/GitHub_Trending/riv/actors

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询