

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 针对 Amazon Bedrock AgentCore Runtime V2 优化你的代理
<a name="runtime-v2-optimize"></a>

Amazon Bedrock AgentCore Runtime V2 通过恢复快照来启动您的代理。这会改变代理代码的结构。您的代理在启动时所做的工作将在快照中捕获，并由每个还原的实例共享。改为在请求处理程序中生成任何在请求之间必须存在差异或可能过期的值。本主题介绍如何围绕启动工作和每个请求的工作来构建代理，以便在每次还原后都保持正确。有关平台版本 V2 的概述，请参阅[平台版本](runtime-how-it-works.md#runtime-platform-versions)。

您的代理有两个执行上下文：

启动  
在运行时拍摄快照之前，在进程启动 AgentCore 时运行一次的代码。 AgentCore Runtime 在快照中捕获此代码，每个实例都会继承其结果。

请求处理  
你的`/invocations`处理程序中的代码。此代码在每个实例上的每个请求上运行。

使用一条规则来决定代码的归属。如果该值在快照的生命周期内保持不变，则在启动时计算该值。如果它因请求而异或可能过期，请在您的处理程序中进行计算。 AgentCore Runtime 为每个代理版本拍摄一个快照，并在您创建或更新代理之前使用该快照，因此快照的生命周期就是该版本的生命周期。

## 启动时初始化一次
<a name="_initialize_once_at_startup"></a>

在快照之前，在流程开始时执行昂贵的、可重复使用的工作。例如，导入依赖关系、加载模型权重或从部署包中读取静态配置。使用 S AgentCore DK，在调用之前，在模块范围内完成这项工作`app.run()`。您的代理在`app.run()`运行之前不会在端口 8080 上侦听，因此`/ping`无法成功，并且在启动工作完成之前无法拍摄快照。快照通过构造捕获完全初始化的代理，您无需进行门`/ping`控。在启动后的 120 秒内完成初始化。如果您的代理没有及时恢复正常，则运行时将无法进行运行状况检查。有关`/ping`和`/invocations`端点的更多信息，请参阅[了解 AgentCore 运行时服务合同](runtime-service-contract.md)。

```
import json, pathlib

from bedrock_agentcore.runtime import BedrockAgentCoreApp

# Runs once at import, before app.run() starts the server and before the
# snapshot. Every restored instance inherits these objects.
MODEL = load_model_weights()
SETTINGS = json.loads((pathlib.Path(__file__).parent / "agent.json").read_text())

app = BedrockAgentCoreApp()

@app.entrypoint
def invoke(payload):
    # Per-request work runs here on every instance.
    ...

app.run()  # starts listening on 8080; the snapshot is taken after this
```

如果您的代理运行自己的 HTTP 服务器而不是 AgentCore SDK，请`/ping`仅在初始化完成后才报告健康状态，以便快照捕获完全初始化的代理。

在启动时只读每个实例都相同且不会过期的数据。在处理程序中处理时间敏感的值，例如短期凭证。

**注意**  
不要在启动时计算任何未经重新部署而更改的内容。例如，从 AgentCore Gateway 获取的工具目录看起来像是理想的启动值，因为它加载起来既慢又昂贵，但是在启动时缓存它会在快照时冻结代理的工具清单。

## 让每个请求的状态保持最新
<a name="_keep_per_request_state_fresh"></a>

快照仅捕获一次，并由每个还原的实例共享，因此您的代理在启动时生成的任何值在各个实例之间都是相同的，并且在创建快照时是固定的。处理快照无法在处理`/invocations`程序中携带的值。下表描述了要在处理程序中而不是在启动时计算的值。


| 要执行的操作 | 在处理程序中执行此操作 | Reason | 
| --- | --- | --- | 
| 生成随机值、标识符或标记 | 根据每个请求致电`os.urandom()``secrets`、或 `uuid.uuid4()` |  `os.urandom()`只有在恢复后每次调用它时才会返回新的熵。启动时读取的值会被复制到快照中，并且在每个实例上都是相同的，无论读取时熵源有多好。该`random`模块同样在启动时是种子的，因此恢复的实例会重复相同的序列。 | 
| 读取当前时间 | 为每个请求计算它 | 启动时捕获的时间戳在快照时是固定的。 | 
| 测量经过的时间 | 在处理程序中获取参考时间戳 |  `time.monotonic()`在还原过程中不会向前推进，因此从启动参考中测得的持续时间是错误的，而且看起来不错。 | 
| 使用凭证或令牌 | 过期后刷新它们 | 启动时加载的凭证可能在实例启动之前过期。 | 
| 识别实例或工作人员 | 为每个请求生成 ID；不要从主机派生 | 每个还原的实例都会报告相同的主机名 (`localhost`) 和 PID (`1`)，因此使用其中任何一个作为 ID 都会折叠队列中的指标、日志流和锁所有者。 | 

在启动时构建可重复使用的客户端，并在每次调用时计算每个请求的值。

```
import os, time

# Build reusable clients at startup, before the snapshot. Exercise them here too
# (for example, with a warm-up call) so the setup the client caches — endpoint and
# credential resolution, connection pool — is captured in the snapshot.
client = build_client()
warm_up(client)

@app.entrypoint
def invoke(payload):
    creds = get_credentials()          # refreshed when expired, not read at startup
    request_id = os.urandom(16).hex()  # unique per request
    now = time.time()                  # current time, not snapshot time
    # Handle the request.
```

## 使用快照安全的加密库
<a name="_use_snapshot_safe_cryptographic_libraries"></a>

当 AgentCore Runtime 从快照恢复实例时，从该快照创建的每个实例都以在快照时捕获的相同内存副本开始。这包括加密库中随机数生成器的内部状态，以及代理在初始化期间创建的任何密钥、令牌或标识符。除非恢复后刷新该状态，否则实例可以生成相同的 “随机” 值。

 **当前限制** 

在 Runt AgentCore ime 上，加密库的快照安全版本在恢复后当前不会重新播放。这适用于直接代码部署和容器部署。

 **变通办法** 
+ 在处理请求时生成密钥、密钥、令牌和会话标识符，而不是在代理启动时生成。这样可以避免在从该快照还原的每个实例中使用在 AgentCore Runtime 拍摄快照之前创建的任何值。
+ 即使在处理请求时，也可以直接从操作系统获取随机值，例如 Python `secrets` 或`os.urandom`、Go 或读取`/dev/urandom`。`crypto/rand`不要使用加密库（例如 OpenSSL）中的随机值，因为它们可能会在实例之间重复。

## 联网
<a name="_networking"></a>

在启动时构建客户端，并期望实现透明的重新连接  
你在启动时打开的套接字在恢复后无法存活，但是你的客户端库缓存的设置（服务模型解析、端点解析、凭据解析和连接池）可以存活下来。在启动时构建和运行您的客户端，并期望恢复后的第一个呼叫可以透明地重新建立连接。

不要使用主机名或 PID 作为唯一的实例标识符  
每个恢复的实例都从相同的快照启动，并报告相同的主机名和进程 ID。在每个请求中生成一个唯一的标识符。

避免绑定到固定源端口  
恢复后，在快照时保持的连接将重新建立，并且固定源端口可能会与实例中的替换端口发生冲突。恢复的实例是具有自己的网络命名空间的独立微型虚拟机，因此冲突发生在实例内部，而不是跨实例之间。

## Cross-account 指标和配额
<a name="_cross_account_metrics_and_quotas"></a>

对于跨账户调用，即一个账户中的委托人通过基于资源的策略调用另一个账户拥有的代理运行时，调用的 CloudWatch 指标和速率限制配额使用量将归因于资源所有者的账户。资源所有者是拥有代理运行时的账户。

您还可以在 S [ervice Quotas 控制台中查看计入配额](https://console.amazonaws.cn/servicequotas/home/services/bedrock-agentcore/quotas)的指标。