已开启
[Feature] Agent 实例优雅停机关机流程与连接排空机制 #53
张鑫宇创建于  6月15日
张鑫宇
张鑫宇成员
6月15日 创建

背景

当前 agent-runtime 在停止或重启 Agent 实例时,直接终止子进程/容器,未提供优雅关闭(Graceful Shutdown)机制。这会导致正在处理中的请求被强行中断,客户端收到连接重置或超时错误,影响生产环境的服务可靠性和用户体验。

现状

  • AgentApp 和 BaseApp 的 FastAPI 实例缺少优雅关闭的信号处理
  • stop_agent 接口直接终止进程,未等待正在处理中的请求完成
  • Docker/K8s 部署策略也未配置 preStop hook 或优雅关闭超时
  • 多租户环境下,一个租户实例的终止可能影响共享基础设施上的其他租户

期望行为

  1. 信号处理机制:AgentApp 能捕获 SIGTERM/SIGINT 信号,在关闭前完成正在处理的请求
  2. 可配置排空超时:支持配置连接排空(connection drain)的超时时间(如 30s/60s)
  3. 健康状态切换:收到停止信号后,首先将健康检查端点返回 503 或从负载均衡摘除,再执行排空
  4. K8s 集成:为 Docker/K8s 部署策略自动生成 preStop hook 配置,与排空超时联动
  5. 日志记录:优雅关闭过程中记录关键事件(开始排空、剩余连接数、排空完成、强制终止等)

建议实现方案

1. AgentApp 层

在 AgentApp 基类中增加 GracefulShutdownMiddleware,在收到停止信号后:

class AgentApp:
    def __init__(self, drain_timeout: int = 30):
        self.drain_timeout = drain_timeout
        self._shutdown_event = asyncio.Event()
        
    async def shutdown_handler(self, sig: int):
        logger.info(f"收到信号 {sig},开始优雅关闭(排空超时:{self.drain_timeout}s)")
        self._shutdown_event.set()
        # 等待正在处理中的请求完成
        await asyncio.sleep(self.drain_timeout)
        logger.info("排空完成,执行最终清理")

2. 部署策略层

  • SubprocessStrategy:通过 process.terminate() 替代 process.kill(),配合 process.wait(timeout=drain_timeout)
  • DockerStrategy:使用 docker stop --time=<drain_timeout> 而非 docker kill
  • K8sStrategy:在 Deployment YAML 中自动注入 terminationGracePeriodSeconds 和 lifecycle.preStop

3. 与健康检查联动

在 HealthService 中暴露一个 is_draining 状态,当实例进入排空阶段时,健康检查端点返回 503 Service Unavailable,这样上游负载均衡器能提前将流量切走。

受影响模块

  • agent_runtime/applications/agent_app/
  • agent_runtime/service/deployment/
  • agent_runtime/service/health/
  • agent_runtime/foundation/
likedislike
openJiuwen-bot成员
6月15日 评论:

欢迎来到 openJiuwen 社区

Hey @xinyu-jiuwen , 感谢你对社区的贡献.

机器人使用手册

有关指令的使用,可以点击 此处 查看详情。开发人员可以在每个PR或Issue下方评论特定指令来触发机器人任务。

likedislike