FEATURED · 精选文章

Gemini Live API SessionManager 实现指南:WebSocket 会话恢复、消息缓冲与重放机制

发布时间 / 2026/9/13 23:34:24
来源 / 创域科博编辑部
栏目 / 资讯中心
Gemini Live API SessionManager 实现指南:WebSocket 会话恢复、消息缓冲与重放机制 Gemini Live API SessionManager 实现指南WebSocket 会话恢复、消息缓冲与重放机制【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills本篇技术指南面向需要基于 WebSocket 为 Gemini Enterprise Live APIBidiGenerateContent双向流式服务实现客户端SessionManager类的开发者详细讲解如何在长连接场景下稳健地管理连接、处理双向通信并通过透明会话恢复transparent session resumption机制在断连后自动重建会话。读完本文你将掌握消息索引与缓冲裁剪的规则、go_away与 WebSocket 错误码1000/1006的断连处理策略以及带消息重放的完整重连流程可直接用于实现生产级 Live API 客户端。文中所有协议字段均以当前仓库中的 client_server_messages.proto 与 client_server_messages.md 为事实依据。背景为什么 Live API 客户端需要一个 SessionManagerGemini Enterprise Live API 通过 WebSocket 暴露双向流式 RPCBidiGenerateContent客户端与模型之间持续交换音频、视频、文本等多种模态的数据。与普通的一次性 HTTP 请求不同这类长连接会话可能持续数分钟甚至更久期间网络抖动、服务端滚动重启go_away都可能导致连接中断。按照 SKILL.md 的说明该 skill 的职责是生成一个连接 Gemini Enterprise Live API WebSocket 端点的客户端服务类处理会话建立/恢复、bearer token 刷新以及ClientMessage/ServerMessageproto 的收发。其中**会话管理session management**是客户端正确性的关键一环如果断连后不能恢复会话上下文用户已经发送但尚未被模型消费的音频、视频帧就会丢失会话被迫从零重建实时体验会大打折扣。SessionManager正是为解决这一问题而设计的核心组件。它负责在断连、重连、缓冲与重放之间维护一致性确保用户感知不到底层连接的切换透明恢复。协议基础ClientMessage / ServerMessage 信封与连接建立在深入会话恢复之前先明确SessionManager所操作的对象。Wire 层协议定义在 client_server_messages.proto 中ClientMessage客户端 → 服务端与ServerMessage服务端 → 客户端都是oneof 信封每个 WebSocket 文本帧恰好设置其中一个字段。ClientMessage的可选字段client_server_messages.proto字段类型使用时机setupBidiGenerateContentSetup仅首帧。配置会话其中就包含session_resumptionclient_contentBidiGenerateContentClientContent追加对话历史、按轮次输入会打断模型realtime_inputBidiGenerateContentRealtimeInput持续低延迟的音/视频/文本输入不进入历史tool_responseBidiGenerateContentToolResponse回复服务端下发的tool_callServerMessage的可选字段client_server_messages.proto字段类型含义setup_completeBidiGenerateContentSetupCompletesetup被接受后发送一次是后续一切发送的门禁server_contentBidiGenerateContentServerContent流式模型输出音频/文本与轮次生命周期tool_callBidiGenerateContentToolCall模型请求执行工具tool_call_cancellationBidiGenerateContentToolCallCancellation取消此前下发的工具调用usage_metadataUsageMetadataToken/时长统计go_awayGoAway连接即将被终止的预告session_resumption_updateSessionResumptionUpdate用于重连的会话句柄更新连接端点见 SKILL.md 的 Validation Checklist为wss://{location}-aiplatform.googleapis.com/ws/google.cloud.aiplatform.v1beta1.LlmBidiService/BidiGenerateContent或全局变体wss://aiplatform.googleapis.com/...setup中的model字段格式为projects/{project_id}/locations/{location}/publishers/google/models/{model_id}。认证通过 Application Default CredentialsADC获取 bearer token以Authorization: Bearer token附加到 WebSocket 握手请求上并在每次重连时重新附加刷新后的 token。SessionManager会话恢复所依赖的两个关键消息正是ClientMessage.setup内的session_resumption字段以及ServerMessage.session_resumption_update字段。SessionManager 的三项核心职责根据 session_manager.mdSessionManager必须承担三项职责连接管理Connection Management持续维护到指定端点的 WebSocket 连接直到被显式停止stop。这意味着连接不是用完即弃而是长驻资源需要围绕它做心跳、断连检测与生命周期管理。双向通信Bidirectional Communication并发地处理发送与接收。由于发送和接收互相独立必须使用独立的协程或线程分别运行发送循环与接收循环——否则接收循环阻塞时发送循环无法感知断连反之亦然。会话恢复Session Resumption发生断连时自动重连并恢复状态。这是下文的主体也是保证用户无感切换连接的基础。透明会话恢复从 setup 消息开始透明会话恢复指客户端在断连后自动重建会话并把断连期间未送达的消息原样重放给模型使模型侧上下文与客户端侧完全一致用户无感知。整个机制由以下四个环节组成。1. 启用透明会话恢复恢复能力不是默认开启的。在初始BidiGenerateContentClientMessage的setup消息类型BidiGenerateContentSetup中必须修改session_resumption字段并在SessionResumptionConfig中始终将transparent字段置为true。对应的 proto 定义client_server_messages.proto 与 L204-L208message BidiGenerateContentSetup { string model 1; // projects/{p}/locations/{l}/publishers/google/models/{m} GenerationConfig generation_config 2; Content system_instruction 3; repeated Tool tools 4; SessionResumptionConfig session_resumption 5; // ← 会话恢复配置 ContextWindowCompressionConfig context_window_compression 6; RealtimeInputConfig realtime_input_config 7; AudioTranscriptionConfig input_audio_transcription 8; AudioTranscriptionConfig output_audio_transcription 9; } message SessionResumptionConfig { string handle 1; // 提供则恢复既有会话省略则开启一个新的可恢复会话 bool transparent 2; // ← 必须置为 true }设置transparent true的效果是服务端会在SessionResumptionUpdate消息中返回last_consumed_client_message_index告诉客户端我已经消费到你发送的第 N 条消息客户端据此裁剪本地缓冲。首帧setup的 JSON 示例如下省略其他字段{ setup: { model: projects/my-proj/locations/us-central1/publishers/google/models/gemini-2.0-flash-live-preview-04-09, generationConfig: { responseModalities: [AUDIO] }, sessionResumption: { transparent: true } } }2. 处理会话句柄更新建立连接后客户端必须持续监听流中的session_resumption_update消息并按以下规则处理若resumable为true且携带了new_handle则保存该句柄该句柄是重连到同一会话的唯一凭证后续任何重连包括go_away与异常断连都必须使用最新保存的句柄。对应的 proto 定义client_server_messages.protomessage SessionResumptionUpdate { string new_handle 1; // 用于恢复的句柄resumablefalse 时为空 bool resumable 2; // 会话当前是否可恢复 int64 last_consumed_client_message_index 3; // 仅当 transparenttrue 时设置 }注意服务端可能多次下发session_resumption_update客户端应始终以最近一次收到的new_handle为准这也与 client_server_messages.md 中在goAway时使用最近一次sessionResumptionUpdate.newHandle重连的规则一致。3. 消息缓冲与裁剪要实现透明重放客户端必须维护一个已发送消息的缓冲以便断连时重放。缓冲的维护遵循以下索引规则索引从 1 开始用户管理的消息索引 MUST 从1起算因为服务端将索引0保留给初始配置消息即首帧setup。绝不使用索引 0 发送用户消息递增此后每发送一条消息索引 1裁剪Pruning收到服务端的session_resumption_update后用其中的last_consumed_client_message_index移除缓冲中已被服务端确认消费的消息。这保证缓冲只保留尚未被确认的消息避免无界增长与重复重放重连时重置重新建立连接后第一条通过新连接传输的消息索引必须重置为1详见下文重连流程。4. 处理断连SessionManager必须同时从发送循环与接收循环两个方向捕获断连并在以下场景触发重连主动重连go_away服务端发送go_away信号携带time_left即连接终止前的剩余时间见 client_server_messages.proto表示连接即将被终止。此时应主动使用最新句柄发起重连而不是被动等待连接断开WebSocket 错误在发送与接收两个循环中捕获 WebSocket 错误**错误码 1000正常关闭或 1006异常关闭**都会触发重连流程意外错误Unexpected Errors对于其他意外错误SessionManager 应当停止并立即抛出该错误后续用户调用 send/receive 时都应抛出带停止原因stop reasons的异常避免在未知状态下继续运行重连过程中的错误Reconnection Errors重连本身也可能失败例如句柄过期、网络持续不可用。这些异常必须正确处理——典型方案是带指数退避exponential backoff的重试或在连接确实无法重建时优雅失败例如回退为开启全新会话。5. 重连与消息重放发生断连后重连流程必须严格按以下顺序执行建立新连接并携带会话句柄建立新的 WebSocket 连接并在新连接的setup.sessionResumption.handle中传入保存的句柄先重放、再收发在发送/接收任何其他消息之前把缓冲中剩余的消息全部重发。重放期间不要修改缓冲——因为此刻仍可能再次断连需要为新的一次重试保留完整的重放数据首个消息索引必须为 1新连接上从缓冲重发的第一条消息索引必须标记为1。这是重连流程中最关键的一条规则索引错误会导致服务端无法对齐消息消费进度收到新的session_resumption_update即重连后的会话句柄更新后才可以根据last_consumed_client_message_index继续裁剪缓冲并恢复正常的收发。重连时携带句柄的setup帧示例如下JSON 字段名采用 camelCase 线格式见 client_server_messages.md 的GoAway resumption示例{ setup: { model: ..., sessionResumption: { handle: ses_xyz } } }对应的服务端预告与句柄更新消息{ goAway: { timeLeft: 10s } } { sessionResumptionUpdate: { newHandle: ses_xyz, resumable: true } }会话恢复的完整时序结合 client_server_messages.md 的 Lifecycle 说明一个含恢复机制的完整会话时序可概括为Client Server │ │ ├── ClientMessage{ setup sessionResumption.transparenttrue } ──► │ │ │ │ ◄────── ServerMessage{ setupComplete } │ ← 收到后才能开始发送 │ ◄────── ServerMessage{ sessionResumptionUpdate{ newHandle, resumable:true } } ├── realtimeInput / clientContent (index1,2,3,...) ──► │ │ ◄────── ServerMessage{ sessionResumptionUpdate{ lastConsumedClientMessageIndex } } │ 据此裁剪缓冲 │ ◄────── serverContent (audio/text stream ...) │ ◄────── goAway { timeLeft } │ ← 预告 │ 客户端主动断连保留缓冲使用最新 newHandle 重连 ├── ClientMessage{ setup sessionResumption.handlenewHandle } ──► ├── 重放缓冲中剩余消息第一条索引 1 ──► │ ◄────── ServerMessage{ sessionResumptionUpdate{ ... } } │ 恢复完成继续正常收发从源码结构看client_server_messages.proto 中GoAway的注释Connection will be terminated soon与SessionResumptionUpdate的注释Resume handle for reconnects以及 client_server_messages.md 中OngoAway, reconnect using the most recentsessionResumptionUpdate.newHandle的规则共同印证了上述流程是协议层明确支持的恢复路径。容易踩的坑Gotchassession_manager.md 专门列出了实现时最容易被忽视的四个陷阱这里逐一展开说明索引 0 不可用用户消息的索引绝不从 0 开始——0 被服务端保留给首帧配置消息setup。如果误用 0服务端会无法区分配置帧与业务帧恢复对齐将直接失效双循环并发接收循环必须能独立检测断连并触发重连即使此时发送循环处于空闲状态反之亦然。如果发送循环空闲没有新数据要发而接收循环被阻塞连接断开将无法被及时发现。这也是职责 2 要求使用独立协程/线程的根本原因句柄过期Handle Expiry会话句柄可能有时效性。如果使用过期句柄重连失败不要无限重试同一句柄——应启动一个全新会话省略handle字段把用户侧已确认的上下文通过clientContent重新注入作为降级路径重放期间修改缓冲从断连到新连接收到句柄更新之间的窗口内缓冲必须保持冻结因为期间任何一次重放失败都需要完整的数据来发起新一轮重试。在 Skill 中的落地生成客户端的验证清单SessionManager并不是孤立组件而是 gemini-live-api 这个 skill 生成的 Live API 客户端服务类的一部分。根据 SKILL.md 的 Validation Checklist生成的客户端必须同时满足以下与会话恢复相关的验收项可直接作为你自己实现的对照清单透明会话恢复已启用session_resumption.transparent true持续跟踪最新new_handle已发送消息的索引从 1 开始通过last_consumed_client_message_index裁剪缓冲重连时重放缓冲中的消息包括go_away与 WebSocket 关闭码 1000/1006 触发的重连认证使用 ADC 提供的 bearer token在过期前刷新并在每次重连时重新附加客户端不面向generativelanguage.googleapis.com也不通过查询串中的 API key 认证。此外生成的客户端应暴露三个异步公共方法均在收到setup_complete后才可调用send_realtime_data(data)携带realtime_input字段的实时输入、send_client_content(data)携带client_content字段的按轮次输入、receive()从 WebSocket 流中产出ServerMessage。从源码结构看SessionManager的发送循环正是这三个公共方法的执行载体而接收循环则是receive()与session_resumption_update监听器的执行载体——两者通过共享的缓冲与句柄状态协同共同构成完整的会话生命周期管理。小结为 Gemini Live API 实现SessionManager本质上是围绕三个不变式来组织代码索引对齐用户消息从 1 开始0 保留给配置、缓冲正确性只保留未确认消息重放期间冻结、重连有序性先带句柄建连、再重放、首个消息索引为 1、收到句柄更新后才恢复裁剪。遵循 session_manager.md 的这组规则配合 client_server_messages.proto 的字段定义与 SKILL.md 的验证清单即可实现一个断连无感、可生产部署的 Live API 双向流式客户端。【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻