

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 針對 Amazon Bedrock AgentCore 執行期 V2 最佳化您的代理程式
<a name="runtime-v2-optimize"></a>

Amazon Bedrock AgentCore 執行期 V2 會透過還原快照來啟動您的代理程式。這會變更您建構代理程式程式碼的方式。您的代理程式在啟動時執行的工作會在快照中擷取，並由每個還原的執行個體共用。改為在請求處理常式中產生請求之間必須不同或可能過期的任何值。本主題說明如何根據啟動工作和每個請求工作來建構代理程式，以便在每次還原後保持正確。如需平台版本 V2 的概觀，請參閱[平台版本](runtime-how-it-works.md#runtime-platform-versions)。

您的代理程式有兩個執行內容：

啟動  
在 AgentCore 執行期擷取快照之前，在程序開始時執行一次的程式碼。AgentCore 執行期會在快照中擷取此程式碼，且每個執行個體都會繼承其結果。

請求處理  
`/invocations` 處理常式中的程式碼。此程式碼會在每個執行個體上的每個請求上執行。

使用一個規則來決定程式碼的所屬位置。如果在快照的生命週期內保持不變，請在啟動時計算值。如果每個請求各有不同或可能過期，請在處理常式中運算。AgentCore 執行期會為每個代理程式版本拍攝一個快照，並用到您建立或更新代理程式為止，因此快照的生命週期是該版本的生命週期。

## 啟動時初始化一次
<a name="_initialize_once_at_startup"></a>

在快照之前，在程序開始時執行昂貴、可重複使用的工作。例如，從部署套件匯入相依性、載入模型權重或讀取靜態組態。使用 AgentCore 開發套件，在呼叫 之前，在模組範圍內執行此工作`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 | 
| --- | --- | --- | 
| 產生隨機值、識別符或字符 | 在每次請求`uuid.uuid4()`時呼叫 `os.urandom()``secrets`、 或 |  `os.urandom()` 只會在您每次在還原之後呼叫它時傳回新的熵。啟動時讀取的值會複製到快照，而且在每個執行個體上都相同，不過熵來源最好是讀取時。`random` 模組也會在啟動時植入，因此還原的執行個體會重複相同的序列。 | 
| 讀取目前時間 | 為每個請求運算 | 啟動時擷取的時間戳記會在快照時修正。 | 
| 測量經過的時間 | 在處理常式中取得參考時間戳記 |  `time.monotonic()` 不會跨還原進行，因此從啟動參考測量的持續時間是錯誤的，而不會顯示錯誤。 | 
| 使用登入資料或字符 | 過期時重新整理它們 | 啟動時載入的登入資料可能會在執行個體啟動之前過期。 | 
| 識別執行個體或工作者 | 為每個請求產生 ID；請勿從主機衍生 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 執行期從快照還原執行個體時，在啟動時快取隨機狀態的密碼編譯程式庫可以在執行個體之間重複使用該狀態。您的密碼編譯程式庫必須使用還原後複寫的快照安全 （快照安全） 建置。

直接程式碼部署  
服務受管基礎映像已包含其密碼編譯程式庫的快照安全組建，因此您不需要對其採取任何動作。

Bring-your-own密碼編譯程式庫  
如果您使用自己的密碼編譯程式庫，例如在容器代理程式中，請使用快照安全組建，以便在還原後重新連接。在 Amazon Linux 2023 上，使用 `openssl-snapsafe-libs`。

## 聯網
<a name="_networking"></a>

在啟動時建置用戶端並預期透明重新連線  
您在啟動時開啟的通訊端不會在還原後存活，但用戶端程式庫在其周圍快取的設定：服務模型剖析、端點解析、憑證解析和連線集區。在啟動時建構和練習您的用戶端，並預期還原後的第一個呼叫會透明地重新建立連線。

請勿使用主機名稱或 PID 做為唯一的執行個體識別符  
每個還原的執行個體都從相同的快照開始，並報告相同的主機名稱和程序 ID。在每個請求中產生唯一識別符。

避免繫結至固定來源連接埠  
還原之後，在快照時間保留的連線會重新建立，且固定來源連接埠可能會與該執行個體中的替代項目衝突。還原的執行個體是具有自己的網路命名空間的個別microVMs，因此衝突是在執行個體內，而不是在執行個體之間。