Rivet Serverless 健康检查失败响应模型解析:RunnerConfigsServerlessHealthCheckResponseOneOf1Failure 与错误信封
2026/9/17 18:08:22 网站建设 项目流程

Rivet Serverless 健康检查失败响应模型解析:RunnerConfigsServerlessHealthCheckResponseOneOf1Failure 与错误信封

【免费下载链接】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 引擎中 serverless 型 runner 配置的健康检查接口,深入解析其失败分支的响应模型RunnerConfigsServerlessHealthCheckResponseOneOf1Failure。文章从 Rust SDK 自动生成的模型定义出发,串联服务端 serverless_health_check.rs 的处理逻辑与 pegboard 层 serverless_metadata/fetch.rs 的元数据抓取实现,完整呈现失败响应的字段结构、错误信封、各类错误kind判别方式及对应的 Rust 代码用法,帮助开发者准确解析健康检查失败原因并据此排查部署问题。

一、模型定位:健康检查响应的失败分支

在 Rivet 的 runner 配置体系中,serverless 型 runner 需要通过POST /runner-configs/serverless-health-check接口验证一个 serverless 端点的元数据是否符合要求。该接口的响应被定义为二选一的枚举:

变体语义
RunnerConfigsServerlessHealthCheckResponseOneOf健康检查成功,携带version字段
RunnerConfigsServerlessHealthCheckResponseOneOf1健康检查失败,携带error字段

其中第二个变体(即本文的主角)是失败分支:RunnerConfigsServerlessHealthCheckResponseOneOf1内部只包含一个failure属性,其类型正是RunnerConfigsServerlessHealthCheckResponseOneOf1Failure。相关枚举定义可查看 RunnerConfigsServerlessHealthCheckResponse.md,两个变体分别对应 RunnerConfigsServerlessHealthCheckResponseOneOf.md 与 RunnerConfigsServerlessHealthCheckResponseOneOf1.md。

二、Failure 模型的属性结构

RunnerConfigsServerlessHealthCheckResponseOneOf1Failure的字段定义如下:

名称类型说明
errormodels::RunnerConfigsServerlessMetadataError必填字段,承载健康检查失败的具体错误信息

该模型只有一个字段error,且为必填。只要健康检查进入失败分支,响应体中必然携带一个结构完整的RunnerConfigsServerlessMetadataError错误对象,不存在空响应或缺失字段的情况。这一约束在 SDK 生成代码中有直接体现——runner_configs_serverless_health_check_response_one_of_1_failure.rs 中error被声明为Box<models::RunnerConfigsServerlessMetadataError>,序列化时使用#[serde(rename = "error")],反序列化时不带Option、无默认值,缺失即报错。

同时,new构造函数强制要求调用方传入RunnerConfigsServerlessMetadataError实例,从类型层面杜绝了构造"不完整的失败响应"的可能性:

pub fn new(error: models::RunnerConfigsServerlessMetadataError) -> RunnerConfigsServerlessHealthCheckResponseOneOf1Failure { RunnerConfigsServerlessHealthCheckResponseOneOf1Failure { error: Box::new(error), } }

三、错误信封:message / details / metadata 三段式结构

error字段引用的RunnerConfigsServerlessMetadataError是服务端暴露给 API 客户端的统一错误信封,其属性如下:

名称类型必填说明
messageString人类可读的错误摘要
detailsOption<String>可选的补充细节(例如被拦截原因)
metadataOption<serde_json::Value>机器可读的结构化信息,metadata.kind用于判别具体错误变体

完整字段文档见 RunnerConfigsServerlessMetadataError.md。其生成代码位于 runner_configs_serverless_metadata_error.rs,源码注释明确指出该类型的用途:无论内部产生哪种ServerlessMetadataError变体,都以稳定的{message, details, metadata}形状暴露给 API 客户端,metadata.kind负责判别变体,各变体专属字段与kind并列存放。

这个"稳定信封"设计源自服务端 serverless_metadata/fetch.rs 中的ServerlessMetadataErrorEnvelope

pub struct ServerlessMetadataErrorEnvelope { pub message: String, #[serde(default, skip_serializing_if = "Option::is_none")] pub details: Option<String>, #[serde(default)] pub metadata: serde_json::Value, }

三个字段中只有message是必需的,details缺省时不输出(skip_serializing_if),metadata缺省时为空对象。这样客户端只需要解析一份固定结构的 JSON,即可覆盖全部失败场景,无需针对每种错误分别建模。

四、错误变体全表:metadata.kind 判别依据

健康检查最终由 pegboard 的pegboard_serverless_metadata_fetch操作执行,其内部ServerlessMetadataError枚举覆盖了从请求发起到响应校验的完整失败链(见 serverless_metadata/fetch.rs)。每个变体经From转换后生成对应的信封,下表汇总了各变体的kindmessagemetadata中携带的附加字段:

metadata.kindmessage内容detailsmetadata附加字段
invalid_requestinvalid serverless metadata request
destination_blockedserverless endpoint is not an allowed destination被拦截的原因reason
request_failedfailed to reach serverless endpoint
request_timed_outserverless metadata request timed out
non_success_statusserverless metadata request returned status {code}status_codebody
invalid_response_jsonserverless metadata response is not valid JSONbodyparse_error
invalid_response_schemaserverless runtime {runtime} version {version} is unsupportedruntimeversion
invalid_envoy_protocol_versionenvoy protocol version {v} is not supported (max supported: {max})envoy_protocol_versionmax_supported_envoy_protocol_version

转换实现位于 serverless_metadata/fetch.rs。可以看出,metadata.kind是结构化的判别键,客户端应优先读取它来区分失败类别,而不是依赖对message文本的字符串匹配——文本内容在 SDK 迭代中可能变化,而kind是稳定的契约。

4.1 各失败类别的触发场景

结合抓取操作的实际代码路径,可推断各kind的触发条件:

  • invalid_request:URL 为空、URL 无法解析,或请求头名称/值不是合法的 HTTP 头(fetch.rs)。
  • destination_blocked:目标 URL 未通过 outbound 策略检查,或 DNS 解析出被禁止的地址。抓取操作通过rivet_pools::reqwest::outbound_policy做前置校验,并对运行期错误二次调用rivet_outbound_guard::block_reason兜底(fetch.rs)。
  • request_failed/request_timed_out:HTTP 请求本身失败或超过 10 秒超时(REQUEST_TIMEOUT常量,见 fetch.rs)。
  • non_success_status:目标端点返回非 2xx 状态码,body为响应体截断后的内容(最大 1024 字符,见 fetch.rs)。
  • invalid_response_json:响应体无法按ServerlessMetadataPayload反序列化。
  • invalid_response_schema:响应可解析但runtime != "rivetkit"version为空(fetch.rs)。
  • invalid_envoy_protocol_versionenvoy_protocol_version小于 1 或超过引擎集群协商的最大版本(上限取ctx.config().protocols().envoy.version(),而非当前二进制编译版本,避免旧 pod 无法与新版 runner 通信,见 fetch.rs)。

五、服务端如何组装失败响应

RunnerConfigsServerlessHealthCheckResponseOneOf1Failure对应的服务端逻辑在 serverless_health_check.rs 中定义:

#[derive(Deserialize, Serialize, ToSchema)] #[serde(rename_all = "snake_case")] pub enum ServerlessHealthCheckResponse { Success { version: String }, Failure { error: ServerlessMetadataErrorEnvelope }, }

处理流程(serverless_health_check_inner)非常简单:先进行身份认证(ctx.auth()),然后调用fetch_serverless_metadata抓取目标端点的元数据:

  • 抓取成功:返回Success { version },即 RunnerConfigsServerlessHealthCheckResponseOneOfSuccess 模型,version是 runner 的元数据版本;
  • 抓取失败:返回Failure { error },即本文主题模型,errorServerlessMetadataErrorFrom自动转换为信封(error.into())。

值得注意的是,健康检查失败并不会导致 HTTP 错误状态码——只要请求与认证本身成功,服务端始终返回 200,失败信息统一放在Failure分支体内。客户端需要先判别是Success变体还是Failure变体,再决定读取version还是解析error

六、Rust SDK 实战:请求与失败解析

健康检查的完整调用链在 runner_configs_serverless_health_check_api.rs 中生成:

  • 请求方法:POST
  • 路径:/runner-configs/serverless-health-check
  • Query 参数:namespace(必填,Rivet 中用于 ACL 区分)
  • 请求体:RunnerConfigsServerlessHealthCheckRequest,包含必填的url与可选的headersHashMap<String, String>
  • 认证方式:bearer_auth(Bearer Token)
  • Content-Type / Accept 均为application/json

Rust 侧的调用与匹配解析示例:

use rivet_api_full::apis::{configuration::Configuration, runner_configs_serverless_health_check_api}; use rivet_api_full::models::{RunnerConfigsServerlessHealthCheckRequest, RunnerConfigsServerlessHealthCheckResponse}; let config = Configuration::new("your-bearer-token".to_string()); let req = RunnerConfigsServerlessHealthCheckRequest::new( "https://serverless.example.com".to_string(), ); let resp = runner_configs_serverless_health_check_api::runner_configs_serverless_health_check( &config, "my-namespace", req, ) .await?; match resp { RunnerConfigsServerlessHealthCheckResponse::RunnerConfigsServerlessHealthCheckResponseOneOf(success) => { println!("健康检查通过,version = {}", success.success.version); } RunnerConfigsServerlessHealthCheckResponse::RunnerConfigsServerlessHealthCheckResponseOneOf1(failure) => { let err = failure.failure.error; // 优先用 metadata.kind 做结构化判别 if let Some(metadata) = err.metadata { if let Some(kind) = metadata.get("kind").and_then(|v| v.as_str()) { println!("失败类别: {kind}"); } } eprintln!("错误信息: {}", err.message); if let Some(details) = err.details { eprintln!("补充细节: {details}"); } } }

七、跨 SDK 的对应类型

该模型不只存在于 Rust SDK,其他语言 SDK 也以对应命名生成:

  • TypeScriptRunnerConfigsServerlessHealthCheckResponseFailureFailure,见 engine/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessHealthCheckResponseFailureFailure.ts,其error对应RunnerConfigsServerlessMetadataError(engine/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataError.ts)。
  • Go:对应类型定义于 engine/sdks/go/api-full/types.go,客户端方法在 engine/sdks/go/api-full/client/client.go 中。

所有 SDK 的模型均由 OpenAPI 规范(engine/artifacts/openapi.json)统一生成,字段结构与本文描述一致,跨语言解析失败响应的方式完全相同。

八、排查建议:从 failure 到根因

当收到Failure分支响应时,建议按以下顺序排查:

  1. metadata.kind:确定失败类别(网络问题、被拦截、非 2xx、JSON 解析失败、协议版本不兼容等);
  2. message:获取面向人的错误摘要,如 "serverless metadata request returned status 404";
  3. kind读取附加字段:如non_success_statusstatus_code/bodydestination_blockedreasoninvalid_envoy_protocol_version的版本号等;
  4. 核对抓取端约束:目标地址必须通过引擎 outbound 策略、响应须在 10 秒内返回、响应体须符合ServerlessMetadataPayload结构(runtimerivetkitversion非空)、envoy_protocol_version须在[1, max_supported]区间内。

其中invalid_envoy_protocol_version对生产环境尤为关键:上限是引擎集群协商出的协议版本,若 runner 携带了较新的协议版本而集群中仍有旧 pod,则该 runner 无法被调度服务,健康检查会如实报错,避免上线后出现版本不匹配的运行时故障。

参考资料

  • 模型文档:RunnerConfigsServerlessHealthCheckResponseOneOf1Failure.md、RunnerConfigsServerlessMetadataError.md、RunnerConfigsServerlessHealthCheckApi.md
  • Rust 生成代码:runner_configs_serverless_health_check_response_one_of_1_failure.rs、runner_configs_serverless_metadata_error.rs、runner_configs_serverless_health_check_api.rs
  • 服务端实现:serverless_health_check.rs
  • 底层抓取与错误枚举:serverless_metadata/fetch.rs

【免费下载链接】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),仅供参考

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

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

立即咨询