AgentCore 新运行时:回收会话内存,让智能体冷启动更可预测

2026-09-18 20 预计阅读时间: 1 分钟
来源: aws.amazon.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

生产级智能体的难点,往往不在于完成一次推理,而在于同时承载大量生命周期不同的会话。Amazon Bedrock AgentCore 新运行时针对这一问题进行了调整:会话释放内存后,运行时能够回收这些资源;同时,即使容器镜像大小和并发水平发生变化,也能保持更一致的冷启动表现。

这两项能力直接影响容量规划、延迟尾部和运行成本,但“更一致”并不等于业务天然获得固定延迟。模型调用、工具链、网络连接和应用初始化仍然需要单独测量。

从常驻内存转向会话级弹性

智能体通常比普通 HTTP 接口拥有更复杂的状态:对话上下文、工具执行结果、临时文件以及检索数据都可能跟随会话存在。如果已结束会话占用的内存不能及时释放,服务会逐渐出现几个问题:

  • 单个实例能够承载的活跃会话数下降;
  • 突发流量更容易触发扩容;
  • 长时间运行后,内存水位与实际活跃会话数不再匹配;
  • 容量估算不得不为历史峰值保留较大余量。

新运行时会随着会话释放内存,使资源使用更贴近当前工作集。对团队而言,这意味着容量模型应从“启动多少个长期驻留进程”转向“当前有多少活跃会话,每个会话持有多少资源”。

不过,运行时能够回收会话内存,并不代表应用代码可以忽略资源生命周期。全局缓存、未关闭的文件、后台线程以及 SDK 连接池仍可能持续占用资源。应用层资源和运行时托管的会话资源应分开观察。

冷启动一致性比单次最快更有价值

在交互式智能体中,偶尔出现一次很慢的启动,通常比平均延迟略高更容易破坏体验。新运行时强调在不同镜像大小和并发条件下保持一致的冷启动,这有助于减少部署包增长或流量突发带来的延迟波动。

这里需要区分三段时间:

  1. 运行时启动时间:由 AgentCore 运行环境负责;
  2. 应用初始化时间:例如导入依赖、读取配置和创建客户端;
  3. 首次任务时间:包括模型推理、知识库检索和外部工具调用。

运行时优化主要解决第一段的可预测性。若应用在模块加载阶段下载模型、扫描大目录或同步连接多个外部系统,最终用户仍可能看到较高的首次响应延迟。因此,镜像大小可以不再是冷启动波动的主要变量,但应用初始化路径依旧值得精简。

用自己的工作负载验证冷启动与并发

公告没有给出适用于所有智能体的统一延迟数字,生产团队应使用自己的镜像、提示词、工具和模型做基准测试。下面的 Python 脚本会创建新的会话 ID,并发调用一个 HTTP 入口,统计成功率以及 p50、p95、p99 延迟。

示例假设接口接受 sessionIdinput 字段。运行前请将它们改成实际 AgentCore 入口要求的请求格式,并按部署方式补充认证;如果入口不是 Bearer Token 认证,则需要替换脚本中的请求签名逻辑。

#!/usr/bin/env python3
import json
import os
import statistics
import time
import uuid
from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen

ENDPOINT = os.environ['AGENT_ENDPOINT']
TOKEN = os.getenv('AUTH_TOKEN')
REQUESTS = int(os.getenv('REQUESTS', '40'))
CONCURRENCY = int(os.getenv('CONCURRENCY', '10'))
TIMEOUT = float(os.getenv('TIMEOUT', '60'))


def invoke(index):
    payload = json.dumps({
        'sessionId': f'benchmark-{uuid.uuid4()}',
        'input': f'Reply with pong. Request number: {index}'
    }).encode('utf-8')

    headers = {'Content-Type': 'application/json'}
    if TOKEN:
        headers['Authorization'] = f'Bearer {TOKEN}'

    request = Request(ENDPOINT, data=payload, headers=headers, method='POST')
    started = time.perf_counter()

    try:
        with urlopen(request, timeout=TIMEOUT) as response:
            response.read()
            elapsed_ms = (time.perf_counter() - started) * 1000
            return response.status, elapsed_ms, None
    except HTTPError as exc:
        return exc.code, (time.perf_counter() - started) * 1000, str(exc)
    except URLError as exc:
        return 0, (time.perf_counter() - started) * 1000, str(exc)


def percentile(values, percentile_value):
    ordered = sorted(values)
    position = round((len(ordered) - 1) * percentile_value)
    return ordered[position]


with ThreadPoolExecutor(max_workers=CONCURRENCY) as pool:
    futures = [pool.submit(invoke, i) for i in range(REQUESTS)]
    results = [future.result() for future in as_completed(futures)]

successful = [latency for status, latency, _ in results if 200 <= status < 300]
failed = [(status, error) for status, _, error in results if not 200 <= status < 300]

print(f'requests={REQUESTS} concurrency={CONCURRENCY}')
print(f'succeeded={len(successful)} failed={len(failed)}')

if successful:
    print(f'mean_ms={statistics.mean(successful):.1f}')
    print(f'p50_ms={percentile(successful, 0.50):.1f}')
    print(f'p95_ms={percentile(successful, 0.95):.1f}')
    print(f'p99_ms={percentile(successful, 0.99):.1f}')

if failed:
    print('sample_failures=', failed[:5])

保存为 benchmark_agent.py 后运行:

export AGENT_ENDPOINT='https://your-agent-endpoint.example/invoke'
export AUTH_TOKEN='replace-if-required'

REQUESTS=20 CONCURRENCY=1 python3 benchmark_agent.py
REQUESTS=100 CONCURRENCY=10 python3 benchmark_agent.py
REQUESTS=200 CONCURRENCY=50 python3 benchmark_agent.py

每次请求都使用新的会话 ID,但这并不自动保证每次都是底层冷启动。要验证冷启动,应按照实际部署的空闲回收策略安排测试窗口,并结合服务端日志或指标确认实例确实经历了启动。建议分别测试小镜像与大镜像、低并发与高并发,并比较延迟分布,而不是只看平均值。

上线前值得确认的事项

采用新运行时时,可以按以下清单推进:

  • 记录 p50、p95、p99,而不是只记录平均响应时间;
  • 将运行时启动、应用初始化和首次模型调用分别打点;
  • 观察会话结束后内存是否下降,并排查应用自身的全局缓存;
  • 使用真实工具调用和检索链路测试,不要只发送空提示词;
  • 在突发并发下同时检查延迟、错误率和限流情况;
  • 不要因为运行时对镜像大小不敏感,就停止清理无用依赖和构建层。

AgentCore 新运行时提供的核心价值,是让智能体基础设施更贴近真实会话负载:会话结束后释放资源,扩展时获得更稳定的启动表现。团队仍需控制应用初始化和外部依赖,但容量规划不必再过度围绕镜像大小和不可预测的冷启动波动展开。


相关推荐