

# 为容器映像实现 SnapStart 挂钩
<a name="snapstart-runtime-hooks-custom"></a>

## 概述
<a name="snapstart-custom-overview"></a>

将 SnapStart 与[容器映像](images-create.md)函数搭配使用时，运行时需协调函数生命周期，并在对应生命周期阶段调用快照前挂钩与恢复后挂钩。您可借助这些挂钩，在快照-恢复生命周期的特定节点运行自定义逻辑（例如刷新凭证、为随机数生成器重新设置种子）。若使用支持 SnapStart 的托管运行时，或对应运行时的基础映像（Java 11\+、Python 3.12\+、.NET 8\+），Lambda 将自动协调生命周期。请按照[在 Lambda 函数快照之前或之后实现代码](snapstart-runtime-hooks.md)所述，通过 API 注册挂钩。

若使用自定义基础容器映像、运行时接口客户端（RIC），或是 Lambda 为 provided.al2023、Node.js、Ruby 提供的基础映像，请按本页面步骤启用 SnapStart。

## 先决条件
<a name="snapstart-custom-prerequisites"></a>

当 Lambda 从快照恢复函数时，初始化阶段定义的所有状态（如随机数生成器、唯一 ID、缓存凭证）会在由此快照恢复的全部执行环境间共享。在为基于容器映像的 Lambda 函数启用 SnapStart 前，请查阅[使用 Lambda SnapStart 处理唯一性](snapstart-uniqueness.md)，并确保满足[使用加密安全伪随机数生成器（CSPRNG）](https://docs.amazonaws.cn/lambda/latest/dg/snapstart-uniqueness.html#snapstart-csprng)中列出的各项要求。

确认已满足全部要求后，请从以下两个选项中选择一项：

1. **选项 1：**若需要在恢复函数快照时，通过快照前挂钩和恢复后挂钩运行自定义逻辑，请按照[实现 SnapStart 生命周期挂钩](#snapstart-custom-implement)章节所载说明操作。

1. **选项 2：**若无需使用这些挂钩，可在 Dockerfile 内指定以下标签，为该容器映像启用 SnapStart：

```
LABEL com.amazonaws.lambda.feature.snapstart="Allow"
```

若容器映像既未实现 `/restore/next` API，也未设置该标签，版本发布将会失败。

**注意**  
若采用适用于 Java（11\+）、Python（3.12\+）、.NET（8\+）的 Lambda 托管基础映像，则无需满足这些先决条件，因为这类映像已完成 SnapStart 生命周期协调，且满足唯一性要求。

## 生命周期概述
<a name="snapstart-custom-lifecycle"></a>

下图展示 SnapStart 自定义运行时需要执行的运行时 API 调用顺序。所有调用均属于 Runtime API 合约；其中 \#3、\#4、\#5、\#6 调用为 SnapStart 专用。

![序列图展示 SnapStart 自定义运行时的 Runtime API 调用顺序：初始化、快照前挂钩、GET /runtime/restore/next、恢复后挂钩、标准调用循环。](https://docs.amazonaws.cn/lambda/latest/dg/images/snapstart-custom-runtime-lifecycle.png)


## 实现 SnapStart 生命周期挂钩
<a name="snapstart-custom-implement"></a>

若要在容器映像函数上使用 SnapStart，请按以下步骤操作：

1. **运行快照前挂钩并触发快照流程：**在函数初始化代码的最后一步，按需执行快照前挂钩，触发快照流程。仅当 SnapStart 已启用时才执行上述步骤，可通过校验 `AWS_LAMBDA_INITIALIZATION_TYPE` 境变量的值是否等于 `snap-start` 进行判断。执行已注册的快照前挂钩，再调用 `GET /runtime/restore/next` 触发快照流程。若快照前挂钩抛出异常或返回错误，运行时会将该错误上报至 `/runtime/init/error` 端点。请参见下方伪代码示例：

   ```
   # After all initialization code has finished:
   
       READ initialization_type FROM environment variable "AWS_LAMBDA_INITIALIZATION_TYPE"
   
       IF initialization_type IS "snap-start" THEN
   
           TRY
               EXECUTE registered before-snapshot hooks
           ON ERROR
               POST error to /runtime/init/error
                   SET header  Lambda-Runtime-Function-Error-Type  TO  <Category>.<Reason>
                   SET body    TO  { errorMessage, errorType, stackTrace }
               EXIT process with non-zero code
   
           # Signal readiness for snapshot
           SEND GET request to /runtime/restore/next
           # The request blocks until Lambda restores the execution environment from the snapshot, then returns HTTP 200.
   
       END IF
   ```
**注意**  
初始化阶段与快照前挂钩共用总超时时间：`max(function_timeout, 130 seconds)`。若超出该时限，Lambda 会使 PublishVersion 请求失败。此外，与 `/runtime/invocation/next` 类似，`/runtime/restore/next` 调用为阻塞调用。该调用会保持阻塞，直至 Lambda 从快照恢复执行环境。

1. **运行恢复后挂钩，随后进入调用循环。**当 `GET /runtime/restore/next` 返回 200 时，运行时必须先执行全部已注册的恢复后挂钩，之后才能进入调用循环。若恢复后挂钩执行失败，请向 `/runtime/restore/error`上报错误。恢复后挂钩执行完毕后，调用 `GET /runtime/invocation/next` 进入标准调用循环。自此之后，函数行为与未启用 SnapStart 的函数完全一致。请参见下方伪代码示例：

   ```
   # After the snapshot has been restored
   # (i.e., GET /runtime/restore/next has returned HTTP 200):
   
       TRY
           EXECUTE registered after-restore hooks
       ON ERROR
           POST error to /runtime/restore/error
               SET header  Lambda-Runtime-Function-Error-Type  TO  <Category>.<Reason>
               SET body    TO  { errorMessage, errorType, stackTrace }
   
   # Proceed to the invoke loop
   ```

## 错误处理
<a name="snapstart-custom-error-handling"></a>

若挂钩执行失败，运行时必须向对应的 API 端点上报错误，并退出进程。下表汇总各阶段的处理行为：


| 阶段 | 错误 API 端点 | 失败后会怎样 | 
| --- | --- | --- | 
| 初始化/快照前 | POST /runtime/init/error | Lambda 会使 PublishVersion 请求失败。退出进程。 | 
| 恢复后 | POST /runtime/restore/error | Lambda 会将正在进行的调用标记为失败，并销毁执行环境。退出进程。 | 

对于这两个 API 端点，请将 `Lambda-Runtime-Function-Error-Type` 标头设为 `<Category.Reason>` 格式的值（例如 `Runtime.BeforeSnapshotError` 或 `Runtime.AfterRestoreError`）。错误正文需包含 T`errorMessage`、`errorType`，以及可选的 `stackTrace`。

如需完整的 API 端点规范与响应码，请参见 Runtime API 参考中的 [初始化错误](runtimes-api.md#runtimes-api-initerror) 和 [恢复错误（仅适用于 SnapStart）](runtimes-api.md#runtimes-api-restore-error)。