

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

# 在 Lambda 函數快照之前或之後實作程式碼
<a name="snapstart-runtime-hooks"></a>

您可以在 Lambda 建立快照之前或 Lambda 從快照恢復函數之後，使用執行階段掛鉤來實作程式碼。執行時期勾點有許多用途，包括：
+ **清除和初始化：**建立快照之前，您可以使用執行時期勾點來執行清除或資源釋放操作。還原快照後，您可以使用執行時期勾點重新初始化快照中未擷取的任何資源或狀態。
+ **動態組態：**您可以在建立快照之前或還原之後，使用執行時期勾點動態更新組態或其他中繼資料。如果函數需要適應執行時期環境的變更，這很有用。
+ **外部整合：**您可以使用執行時期勾點與外部服務或系統整合，作為檢查點和還原程序的一部分，藉此完成傳送通知或更新外部狀態等操作。
+ **效能調校：**您可以使用執行時期勾點來微調函數的啟動順序，例如預先載入相依項。如需更多詳細資訊，請參閱 [效能調校](snapstart-best-practices.md#snapstart-tuning)。

以下幾頁說明如何針對您偏好的執行時期實作執行時期勾點。

**Topics**
+ [Java](snapstart-runtime-hooks-java.md)
+ [Python](snapstart-runtime-hooks-python.md)
+ [.NET](snapstart-runtime-hooks-dotnet.md)

# Lambda SnapStart 執行時期勾點 (Java)
<a name="snapstart-runtime-hooks-java"></a>

您可以在 Lambda 建立快照之前或 Lambda 從快照恢復函數之後，使用執行階段掛鉤來實作程式碼。執行階段掛鉤可做為開放原始碼 Coordinated Restore at Checkpoint (CRaC) 專案的一部分使用。目前正在針對 [Java 開發套件 (OpenJDK)](https://wiki.openjdk.org/display/crac) 開發 CRaC。如需如何搭配參考應用程式使用 CRaC 的範例，請參閱 GitHub 上的 [CRaC](https://github.com/CRaC/docs/blob/master/STEP-BY-STEP.md) 儲存庫。CRaC 使用三個主要元素：
+ `Resource` - 具有兩種方法 (`beforeCheckpoint()` 和 `afterRestore()`) 的介面。使用這些方法來實作您想在快照建立之前和還原之後執行的程式碼。
+ `Context <R extends Resource>` - 若要接收檢查點和還原的通知，必須透過 `Context` 註冊 `Resource`。
+ `Core` - 協調服務，透過靜態方法 `Core.getGlobalContext()` 提供預設的全域 `Context`。

如需 `Context` 和 `Resource` 的詳細資訊，請參閱 CRaC 文件中的[套件 org.crac](https://javadoc.io/doc/io.github.crac/org-crac/latest/index.html)。

使用下列步驟，透過 [org.crac 套件](https://github.com/CRaC/org.crac)實作執行階段掛鉤。Lambda 執行階段包含自訂的 CRaC 內容實作，可在檢查點之前和還原之後呼叫執行階段掛鉤。

## 執行時期勾點註冊和執行
<a name="runtime-hooks-registration-java"></a>

Lambda 執行執行時期勾點的順序取決於勾點的註冊順序。註冊順序遵循程式碼中的匯入、定義或執行順序。
+ `beforeCheckpoint()`：依與註冊順序相反的順序執行
+ `afterRestore()`：依註冊順序執行

確定已正確匯入所有已註冊的勾點，並包含在函數的程式碼中。如果您在單獨的檔案或模組中註冊執行時期勾點，則必須確保直接匯入相關模組，或將其作為較大套件的一部分匯入函數的處理常式檔案中。如果未在函數處理常式中匯入相關檔案或模組，則 Lambda 會忽略相關執行時期勾點。

**注意**  
Lambda 建立快照時，初始化程式碼最多可能會執行 15 分鐘。時間上限為 130 秒或[設定的函數逾時](configuration-timeout.md) (最長 900 秒)，以較高者為準。您的 `beforeCheckpoint()` 執行時間掛鉤會計入初始化程式碼時間限制。Lambda 還原快照時，執行時期必須載入，且 `afterRestore()` 執行時期勾點必須在逾時限制 (10 秒) 內完成。否則，您將收到 SnapStartTimeoutException 訊息。

## 步驟 1：更新建置組態
<a name="runtime-hooks-java-update-build"></a>

將 `org.crac` 相依性新增到建置組態。以下範例使用 Gradle。如需其他建置系統的範例，請參閱 [Apache Maven 文件](https://search.maven.org/artifact/io.github.crac/org-crac/0.1.3/jar)。

```
dependencies {
    compile group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.1'
    # All other project dependecies go here:
    # ...
    # Then, add the org.crac dependency:
 implementation group: 'org.crac', name: 'crac', version: '1.4.0'
}
```

## 步驟 2：更新 Lambda 處理常式
<a name="runtime-hooks-java-update-handler"></a>

Lambda 函數*處理常式*是您的函數程式碼中處理事件的方法。當有人呼叫您的函數時，Lambda 會執行處理常式方法。函數會執行，直到處理常式傳回回應、結束或逾時為止。

如需詳細資訊，請參閱[在 Java 中定義 Lambda 函數處理常式](java-handler.md)。

以下處理常式範例示範如何在檢查點之前 (`beforeCheckpoint()`) 和還原之後 (`afterRestore()`) 執行程式碼。此處理常式也會向執行階段管理的全域 `Context` 註冊 `Resource`。

**注意**  
Lambda 建立快照時，初始化程式碼最多可能會執行 15 分鐘。時間上限為 130 秒或[設定的函數逾時](configuration-timeout.md) (最長 900 秒)，以較高者為準。您的 `beforeCheckpoint()` 執行時間掛鉤會計入初始化程式碼時間限制。Lambda 還原快照時，執行階段 (JVM) 必須載入，且 `afterRestore()` 執行階段掛鉤必須在逾時限制 (10 秒) 內完成。否則，您將收到 SnapStartTimeoutException 訊息。

```
...
  import org.crac.Resource;
  import org.crac.Core;
  ... 
public class CRaCDemo implements RequestStreamHandler, Resource {
    public CRaCDemo() {
      Core.getGlobalContext().register(this);
    }
    public String handleRequest(String name, Context context) throws IOException {
      System.out.println("Handler execution");
      return "Hello " + name;
    }
    @Override
    public void beforeCheckpoint(org.crac.Context<? extends Resource> context)
        throws Exception {
      System.out.println("Before checkpoint");
    }
    @Override
    public void afterRestore(org.crac.Context<? extends Resource> context)
        throws Exception {
      System.out.println("After restore");
```

`Context` 僅會對已註冊物件維持 [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/WeakReference.html](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/WeakReference.html)。如果 [https://javadoc.io/static/io.github.crac/org-crac/0.1.3/org/crac/Resource.html](https://javadoc.io/static/io.github.crac/org-crac/0.1.3/org/crac/Resource.html) 是回收的垃圾，則執行階段掛鉤程式不會執行。您的程式碼必須維持對 `Resource` 的強式參考，才能保證執行階段掛鉤會執行。

以下是須避免的兩個模式範例：

**Example - 沒有強式參考的物件**  

```
Core.getGlobalContext().register( new MyResource() );
```

**Example - 匿名類別的物件**  

```
Core.getGlobalContext().register( new Resource() {
   
   @Override
   public void afterRestore(Context<? extends Resource> context) throws Exception {
    // ...
   }
   
   @Override
   public void beforeCheckpoint(Context<? extends Resource> context) throws Exception {
    // ...
   }

} );
```

而是維持強式參考。在下列範例中，已註冊的資源不是回收的垃圾，且執行階段掛鉤會一致地執行。

**Example - 有強式參考的物件**  

```
Resource myResource = new MyResource(); // This reference must be maintained to prevent the registered resource from being garbage collected
Core.getGlobalContext().register( myResource );
```

# Lambda SnapStart 執行時期勾點 (Python)
<a name="snapstart-runtime-hooks-python"></a>

您可以在 Lambda 建立快照之前或 Lambda 從快照恢復函數之後，使用執行階段掛鉤來實作程式碼。Python 執行時期勾點作為 [Snapshot Restore for Python library](https://pypi.org/project/snapshot-restore-py/) 的一部分提供，該程式庫包含在 Python 受管執行時期中。此程式庫提供兩個裝飾項目，可用於定義執行時期勾點：
+ `@register_before_snapshot`：用於您要在 Lambda 建立快照之前執行的函數。
+ `@register_after_restore`：用於您要在 Lambda 從快照恢復函數時執行的函數。

您也可以使用以下方法來註冊執行時期勾點的可呼叫項：
+ `register_before_snapshot(func, *args, **kwargs)`
+ `register_after_restore(func, *args, **kwargs)`

## 執行時期勾點註冊和執行
<a name="runtime-hooks-registration-python"></a>

Lambda 執行執行時期勾點的順序取決於勾點的註冊順序：
+ 快照之前：依與註冊順序相反的順序執行
+ 快照之後：依註冊順序執行

執行時期勾點註冊的順序取決於您如何定義勾點。使用裝飾項目 (`@register_before_snapshot` 和 `@register_after_restore`) 時，註冊順序會遵循程式碼中的匯入、定義或執行順序。如果您需要對註冊順序進行更多控制，請使用 `register_before_snapshot()` 和 `register_after_restore()` 方法，而不要使用裝飾項目。

確定已正確匯入所有已註冊的勾點，並包含在函數的程式碼中。如果您在單獨的檔案或模組中註冊執行時期勾點，則必須確保直接匯入相關模組，或將其作為較大套件的一部分匯入函數的處理常式檔案中。如果未在函數處理常式中匯入相關檔案或模組，則 Lambda 會忽略相關執行時期勾點。

**注意**  
Lambda 建立快照時，初始化程式碼最多可能會執行 15 分鐘。時間上限為 130 秒或[設定的函數逾時](configuration-timeout.md) (最長 900 秒)，以較高者為準。您的 `@register_before_snapshot` 執行時間掛鉤會計入初始化程式碼時間限制。Lambda 還原快照時，執行時期必須載入，且 `@register_after_restore` 執行時期勾點必須在逾時限制 (10 秒) 內完成。否則，您將收到 SnapStartTimeoutException 訊息。

## 範例
<a name="runtime-hooks-python-code-sample"></a>

以下處理常式範例示範如何在檢查點之前 (`@register_before_snapshot`) 和還原之後 (`@register_after_restore`) 執行程式碼。

```
from snapshot_restore_py import register_before_snapshot, register_after_restore

def lambda_handler(event, context):
    # Handler code

@register_before_snapshot
def before_checkpoint():
    # Logic to be executed before taking snapshots

@register_after_restore
def after_restore():
    # Logic to be executed after restore
```

如需更多範例，請參閱 AWS GitHub 儲存庫中的 [Snapshot Restore for Python](https://github.com/aws/snapshot-restore-py/tree/main/examples)。

# Lambda SnapStart 執行時期勾點 (.NET)
<a name="snapstart-runtime-hooks-dotnet"></a>

您可以在 Lambda 建立快照之前或 Lambda 從快照恢復函數之後，使用執行階段掛鉤來實作程式碼。[Amazon.Lambda.Core](https://www.nuget.org/packages/Amazon.Lambda.Core) 套件 (2.5.0 版或更新版本) 提供 .NET 執行時期勾點。此程式庫提供兩種定義執行時期勾點的方法：
+ `RegisterBeforeSnapshot()`：建立快照前執行的程式碼
+ `RegisterAfterSnapshot()`：從快照恢復函數後執行的程式碼

**注意**  
如果使用的是[適用於 .NET 的 Lambda Annotations 架構](csharp-handler.md#csharp-handler-annotations)，請升級至 [Amazon.Lambda.Annotations](https://www.nuget.org/packages/Amazon.Lambda.Annotations) 1.6.0 版或更新版本，以確保與 SnapStart 的相容性。

## 執行時期勾點註冊和執行
<a name="runtime-hooks-registration-dotnet"></a>

在初始化程式碼中註冊勾點。根據 Lambda 函數的[執行模型](csharp-handler.md#csharp-handler-setup)考慮下列準則：
+ 對於[可執行的組裝方法](csharp-handler.md#csharp-executable-assembly-handlers)，請在使用 `RunAsync` 啟動 Lambda 引導程序之前註冊勾點。
+ 對於[類別程式庫方法](csharp-handler.md#csharp-class-library-handlers)，請在處理常式類別建構函數中註冊勾點。
+ 對於 [ASP.NET Core 應用程式](csharp-package-asp.md)，請先註冊勾點，再呼叫 `WebApplications.Run` 方法。

若要在 .NET 中註冊 SnapStart 的執行時期勾點，請使用以下方法：

```
Amazon.Lambda.Core.SnapshotRestore.RegisterBeforeSnapshot(BeforeCheckpoint);
Amazon.Lambda.Core.SnapshotRestore.RegisterAfterRestore(AfterCheckpoint);
```

註冊多個勾點類型時，Lambda 執行執行執行時期勾點的順序取決於勾點的註冊順序：
+ `RegisterBeforeSnapshot()`：依與註冊順序相反的順序執行
+ `RegisterAfterSnapshot()`：依註冊順序執行

**注意**  
Lambda 建立快照時，初始化程式碼最多可能會執行 15 分鐘。時間上限為 130 秒或[設定的函數逾時](configuration-timeout.md) (最長 900 秒)，以較高者為準。您的 `RegisterBeforeSnapshot()` 執行時間掛鉤會計入初始化程式碼時間限制。Lambda 還原快照時，執行時期必須載入，且 `RegisterAfterSnapshot()` 執行時期勾點必須在逾時限制 (10 秒) 內完成。否則，您將收到 SnapStartTimeoutException 訊息。

## 範例
<a name="runtime-hooks-dotnet-code-sample"></a>

以下函數範例示範如何在檢查點之前 (`RegisterBeforeSnapshot`) 和還原之後 (`RegisterAfterRestore`) 執行程式碼。

```
public class SampleClass
{
    public SampleClass()
    {
        Amazon.Lambda.Core.SnapshotRestore.RegisterBeforeSnapshot(BeforeCheckpoint);
        Amazon.Lambda.Core.SnapshotRestore.RegisterAfterRestore(AfterCheckpoint);
    }

    private ValueTask BeforeCheckpoint()
    {
        // Add logic to be executed before taking the snapshot
        return ValueTask.CompletedTask;
    }

    private ValueTask AfterCheckpoint()
    {
        // Add logic to be executed after restoring the snapshot
        return ValueTask.CompletedTask;
    }

    public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
    {
        // Add business logic

        return new APIGatewayProxyResponse
        {
            StatusCode = 200
        };
    }
}
```