Files
2026-06-01 13:54:52 +08:00

18 KiB
Raw Permalink Blame History

会话缓存机制

**本文引用的文件** - [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs) - [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs) - [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs) - [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs) - [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs) - [model.rs](file://crates/agent_runner/src/model.rs) - [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件系统性阐述 session_cache 模块如何管理 AI 代理会话状态,涵盖缓存数据结构设计、生命周期管理策略、并发访问控制机制、缓存项的创建/更新/清理流程,以及与代理服务的交互模式。文档还记录内存使用特征、过期策略与性能优化措施,并提供聊天交互与进度查询的实际使用场景示例。

项目结构

围绕会话缓存的关键文件组织如下:

  • 会话缓存核心session_cache.rs
  • SSE 进度通知agent_session_notification.rs
  • 聊天入口与会话清理chat_handler.rs
  • 清理任务与资源回收cleanup_task.rs
  • 统一消息模型与通知agent_session_notify.rs、model.rs
  • 代理侧会话通知转发proxy_agent/mod.rs
graph TB
subgraph "会话缓存层"
SC["SessionData<br/>环形缓冲区+命令通道"]
PC["PROJECT_SESSION_MAP<br/>项目-会话映射"]
GC["全局缓存 SESSION_CACHE<br/>按session_id索引"]
end
subgraph "代理侧"
AC["AcpAgentClient<br/>session_notification回调"]
PRJ["PROJECT_AND_AGENT_INFO_MAP<br/>项目-代理状态"]
end
subgraph "HTTP处理层"
SSE["SSE 进度接口<br/>agent_session_notification.rs"]
CHAT["聊天接口<br/>chat_handler.rs"]
end
subgraph "清理与回收"
CLEAN["清理任务<br/>cleanup_task.rs"]
end
AC --> |"推送通知"| SC
SSE --> |"建立SSE并创建SessionData"| GC
CHAT --> |"清理旧会话/新会话"| GC
CLEAN --> |"定期扫描并清理"| GC
CLEAN --> |"清理映射"| PC
AC --> |"回填request_id上下文"| AC

图表来源

章节来源

核心组件

  • 全局会话缓存 SESSION_CACHE以 session_id 为键,存储每个会话的 SessionData。
  • 项目-会话映射 PROJECT_SESSION_MAP确保同一项目仅有一个活跃会话变更时自动清理旧会话。
  • SessionData封装环形缓冲区、命令通道、当前发送器与取消令牌负责消息入队、实时推送与连接关闭。
  • SessionWorker后台工作者消费命令通道维护环形缓冲区按需实时推送消息。
  • 统一会话消息 UnifiedSessionMessage 与通知 SessionNotify标准化消息格式便于跨组件传递。
  • SSE 进度接口 agent_session_notification为前端建立 SSE 连接,实时推送会话状态。
  • 清理任务 cleanup_task定期扫描并清理闲置代理与孤立会话。

章节来源

架构总览

会话缓存的整体交互链路如下:

  • 代理侧 AcpAgentClient 在收到 session_notification 后,构造 SessionNotify 并调用 push_session_update统一转为 UnifiedSessionMessage 写入 SessionData。
  • SSE 进度接口 agent_session_notification 为每个 session_id 创建新的 SessionData 并插入 SESSION_CACHE随后创建连接并持续推送消息。
  • 聊天接口 chat_handler 在发起新请求前,会清理旧会话,确保全新开始。
  • 清理任务定期扫描 PROJECT_SESSION_MAP 与 SESSION_CACHE清理孤立会话与闲置代理。
sequenceDiagram
participant Agent as "代理(AcpAgentClient)"
participant Cache as "SessionData/Worker"
participant SSE as "SSE接口"
participant Front as "前端"
Agent->>Cache : "push_session_update(SessionNotify)"
Cache->>Cache : "SessionWorker : Push消息到环形缓冲区"
Cache->>Cache : "尝试实时推送至当前发送器"
SSE->>Cache : "create_new_connection(新建SessionData)"
Cache-->>SSE : "返回接收端+取消令牌"
loop "SSE循环"
Cache-->>SSE : "推送UnifiedSessionMessage"
SSE-->>Front : "SSE事件"
end
Note over SSE,Cache : "取消令牌触发或发送端关闭时SSE断开"

图表来源

详细组件分析

会话缓存数据结构与生命周期

  • 数据结构设计
    • SESSION_CACHE全局 DashMap键为 session_id值为 Arc保证并发安全与零拷贝共享。
    • SessionData包含命令发送端、当前发送器与取消令牌的互斥保护避免竞态。
    • SessionWorker持有环形缓冲区HeapRb按最大容量维护消息队列实时推送失败时自动清理当前发送器。
    • PROJECT_SESSION_MAP全局 DashMap键为 project_id值为 session_id确保同一项目仅有一个活跃会话。
  • 生命周期管理
    • 新建SSE 接口为每个 session_id 创建新的 SessionData 并插入 SESSION_CACHE覆盖旧值确保“全新开始”。
    • 销毁SessionWorker 退出时SessionData 仍驻留缓存;清理任务通过移除映射与缓存条目实现资源回收。
    • 连接关闭:主动触发 CancellationToken 或显式关闭发送端,使接收端 recv() 返回 NoneSSE 自然断开。
classDiagram
class SessionData {
+command_tx
+current_sender
+current_cancel
+new(max_size)
+create_new_connection(buffer_size)
+push_message(message)
+close_current_connection()
+message_count()
}
class SessionWorker {
-max_size
-command_rx
-current_sender
-current_cancel
+spawn(...)
+run()
}
class UnifiedSessionMessage {
+session_id
+message_type
+sub_type
+data
+timestamp
+heartbeat(session_id)
}
class SessionNotify {
+to_unified_message()
}
SessionData --> SessionWorker : "spawn并消费命令"
SessionWorker --> UnifiedSessionMessage : "生产消息"
SessionNotify --> UnifiedSessionMessage : "转换"

图表来源

章节来源

并发访问控制机制

  • 全局缓存与映射
    • 使用 LazyLock 初始化 DashMap保证线程安全与延迟初始化。
    • SessionData 内部对 current_sender/current_cancel 使用 Mutex 包裹,避免多处同时写入导致的竞争。
  • 命令通道
    • SessionData 内部使用无界 mpsc 通道接收命令SessionWorker 异步消费,避免阻塞代理通知路径。
  • 取消令牌
    • 每次创建新连接都会生成新的 CancellationToken旧连接一旦被新连接抢占或用户取消立即触发取消确保旧连接快速失效。

章节来源

缓存项创建、更新与清理流程

  • 创建
    • SSE 接口为 session_id 创建 SessionData 并插入 SESSION_CACHE同时创建连接并返回接收端与取消令牌。
  • 更新
    • 代理侧 session_notification 回调将 SessionUpdate 转为 SessionNotify再转为 UnifiedSessionMessage通过 SessionData.push_message 入队。
    • SessionWorker 将消息写入环形缓冲区,并尝试实时推送至当前发送器;若推送失败则清空当前发送器,避免脏写。
  • 清理
    • SSE 接口当取消令牌被触发或发送端关闭时SSE 断开,旧 SessionData 仍保留,等待清理任务回收。
    • 清理任务:扫描 PROJECT_SESSION_MAP 与 SESSION_CACHE移除孤立会话与空闲代理减少内存占用。
flowchart TD
Start(["开始"]) --> Create["SSE接口创建SessionData并插入缓存"]
Create --> Push["代理推送SessionNotify->UnifiedSessionMessage"]
Push --> Buffer["SessionWorker写入环形缓冲区"]
Buffer --> Realtime{"实时推送成功?"}
Realtime --> |是| SSELoop["SSE循环推送消息"]
Realtime --> |否| ClearSender["清空当前发送器"]
SSELoop --> Cancel{"取消令牌触发/发送端关闭?"}
Cancel --> |是| Close["SSE断开旧SessionData保留"]
Cancel --> |否| Heartbeat["周期心跳"]
Close --> Cleanup["清理任务扫描并移除"]
Cleanup --> End(["结束"])

图表来源

章节来源

与代理服务的交互模式

  • 代理侧 AcpAgentClient 实现 session_notification 回调,将 ACP SessionUpdate 转为 AgentSessionUpdate再包装为 SessionNotify最终调用 push_session_update 写入缓存。
  • 若 SessionNotification.meta 中未携带 request_id则通过 PROJECT_AND_AGENT_INFO_MAP 查找 project_id再从 SESSION_REQUEST_CONTEXT 获取 request_id确保消息携带 request_id 以便前端关联。
sequenceDiagram
participant ACP as "ACP客户端"
participant Client as "AcpAgentClient"
participant Cache as "push_session_update"
participant Worker as "SessionWorker"
participant SSE as "SSE接口"
ACP->>Client : "session_notification(SessionUpdate)"
Client->>Client : "提取/回填request_id"
Client->>Cache : "SessionNotify -> UnifiedSessionMessage"
Cache->>Worker : "命令 : Push"
Worker->>Worker : "写入环形缓冲区"
Worker->>SSE : "尝试实时推送"
SSE-->>Client : "SSE循环接收并转发"

图表来源

章节来源

过期策略与内存使用特征

  • 过期策略
    • 心跳消息SSE 接口在建立连接后立即发送心跳,并按周期发送心跳事件,用于维持连接活性。
    • 取消与断开取消令牌触发或发送端关闭时SSE 断开SessionWorker 退出后SessionData 仍驻留缓存,等待清理任务回收。
    • 孤立会话清理:清理任务扫描 SESSION_CACHE 中不在活跃映射中的 session_id若消息计数大于 0 则移除条目,否则标记为空会话清理。
  • 内存使用特征
    • 环形缓冲区:按最大容量维护最近消息,满时淘汰最旧消息,避免无限增长。
    • 连接级缓存:每次 SSE 连接都会创建新的 SessionData覆盖旧值确保不会累积历史消息。
    • 映射表PROJECT_SESSION_MAP 仅保存活跃映射,清理任务移除无效映射,降低内存压力。

章节来源

性能优化措施

  • 极简设计
    • SessionData 直接共享当前发送器与取消令牌,避免命令传递带来的额外开销。
    • SessionWorker 直接从共享状态获取发送器,实时推送失败时立即清空,避免后续无效尝试。
  • 通道与锁粒度
    • 使用无界命令通道与细粒度 Mutex降低锁竞争概率。
  • 心跳与断开
    • 心跳事件降低连接空闲时的网络压力;取消令牌与发送端关闭确保旧连接快速失效,避免资源浪费。
  • 清理策略
    • 定期清理孤立会话与闲置代理,减少缓存与映射膨胀。

章节来源

依赖关系分析

  • 组件耦合
    • session_cache 与 agent_session_notificationSSE 接口依赖 SessionData 的创建与连接能力。
    • proxy_agent/mod 与 session_cache代理侧通知通过 push_session_update 写入缓存,二者通过统一消息模型解耦。
    • chat_handler 与 session_cache聊天接口在发起新请求前清理旧会话确保全新开始。
    • cleanup_task 与 session_cache/PROJECT_SESSION_MAP清理孤立会话与映射避免资源泄漏。
  • 外部依赖
    • DashMap 提供并发安全的哈希表。
    • ringbuf HeapRb 提供高效环形缓冲区。
    • tokio mpsc 提供异步通道与取消令牌。
graph LR
A["agent_session_notification.rs"] --> B["session_cache.rs"]
C["proxy_agent/mod.rs"] --> B
D["chat_handler.rs"] --> B
E["cleanup_task.rs"] --> B
E --> F["PROJECT_SESSION_MAP"]

图表来源

章节来源

性能考量

  • 环形缓冲区容量:根据业务负载调整最大容量,平衡内存占用与消息保留范围。
  • 实时推送失败处理:推送失败时清空发送器,避免后续无效尝试;必要时增加接收端缓冲大小。
  • 心跳频率:合理的心跳间隔可在保持连接活性与网络开销之间取得平衡。
  • 清理周期:清理任务的间隔与闲置超时可根据系统负载动态调整,避免过于频繁或过少。

故障排查指南

  • SSE 连接无法建立
    • 检查 SSE 接口是否成功创建 SessionData 并插入 SESSION_CACHE。
    • 确认 create_new_connection 是否返回接收端与取消令牌。
  • 实时消息未到达前端
    • 检查 SessionWorker 是否成功写入环形缓冲区与尝试实时推送。
    • 若推送失败,确认当前发送器是否被清空,以及取消令牌是否被触发。
  • 旧会话消息残留
    • 确认 SSE 接口是否为每个 session_id 创建新的 SessionData 并覆盖旧值。
    • 检查清理任务是否正确扫描并移除孤立会话。
  • 代理通知未写入缓存
    • 确认 AcpAgentClient 的 session_notification 回调是否正确提取 request_id 并调用 push_session_update。
    • 检查 SessionData 是否存在且未被清理。

章节来源

结论

session_cache 模块通过 SessionData + SessionWorker + 环形缓冲区的组合,实现了高并发、低开销的会话状态缓存与实时推送。配合 SSE 进度接口、聊天入口清理策略与定期清理任务,系统在保证消息实时性的同时,有效控制内存与资源占用,满足 AI 代理会话状态管理的需求。

附录

实际使用场景示例

  • 聊天交互
    • 前端调用聊天接口后端为项目生成或复用会话清理旧会话后启动代理任务SSE 接口实时推送执行进度。
  • 进度查询
    • 前端通过 /agent/progress/{session_id} 建立 SSE 连接,接收 prompt_start、agent_message_chunk、tool_call 等事件,结合心跳维持连接活性。

章节来源