

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

# 使用 Lambda 延伸 API 來建立延伸項目
<a name="runtimes-extensions-api"></a>

Lambda Event Function 作者使用擴充功能，將 Lambda 與其偏好的工具整合，以進行監控、可觀測性、安全性和控管。Event Function 作者可以使用來自 AWS、 [AWS 合作夥伴](extensions-api-partners.md)和開放原始碼專案的擴充功能。如需使用延伸模組的詳細資訊，請參閱運算部落格上的 AWS [介紹 AWS Lambda 延伸](https://aws.amazon.com/blogs/aws/getting-started-with-using-your-favorite-operational-tools-on-aws-lambda-extensions-are-now-generally-available/)模組。本節說明如何使用 Lambda 延伸 API、Lambda 執行環境生命週期以及 Lambda 延伸 API 參考。

![延伸 API 和遙測 API 可連接 Lambda 及外部延伸項目。](https://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/telemetry-api-concept-diagram.png)


作為延伸項目的作者，您可以使用 Lambda Extensions API 以便深入整合到 Lambda [執行環境](lambda-runtime-environment.md)中。您的擴充功能可以註冊 Event Function 和執行環境生命週期事件。為了回應這些事件，您可以啟動新程序、執行邏輯，以及控制並參與 Lambda 生命週期的所有階段：初始化、調用和關閉。此外，您可以使用 [Runtime Logs API](runtimes-logs-api.md) 來接收日誌串流。

延伸項目會在執行環境中做為獨立程序執行，並在事件函數呼叫完全處理後繼續執行。由於延伸項目會做為程序執行，因此您可以使用與 Event Function 不同的語言撰寫。我們建議您使用編譯語言實作延伸項目。

在這種情況下，延伸項目是獨立的二進位檔案，會與支援的執行時間相容。所有 [Lambda 事件函數執行時間](lambda-runtimes.md) 支援延伸。如果您使用非編譯語言，請確定您在延伸項目中包含相容的執行階段。

Lambda 也支援內部*延伸項目*。內部延伸項目會作為獨立執行緒在執行時間程序中執行。執行時間會啟動並停止內部延伸項目。與 Lambda 環境整合的另一種方法是使用特定語言的[環境變數和包裝函數指令碼](runtimes-modify.md)。您可使用這些來設定執行時間環境，並修改執行時間程序的啟動行為。

您可以透過兩種方式將延伸項目新增至事件函數。對於部署為 [.zip 檔案封存](configuration-function-zip.md)的事件函數，您可以將擴充功能部署為 [layer](chapter-layers.md)。對於定義為容器映像的事件函數，您可以將[延伸](extensions-configuration.md#invocation-extensions-images)項目新增至容器映像。

**注意**  
如需延伸項目和包裝函式指令碼的範例，請參閱 AWS 範例 GitHub 儲存庫上的[AWS Lambda 延伸](https://github.com/aws-samples/aws-lambda-extensions)項目。

**Topics**
+ [Lambda 執行環境生命週期](#runtimes-extensions-api-lifecycle)
+ [Extensions API 參考](#runtimes-extensions-registration-api)

## Lambda 執行環境生命週期
<a name="runtimes-extensions-api-lifecycle"></a>

執行環境的生命週期包含下列階段：
+ `Init`：在此階段，Lambda 會使用設定的資源建立或取消凍結執行環境、下載 Event Function 和所有 layer 的程式碼、初始化任何延伸、初始化執行時間，然後執行 Event Function 的初始化程式碼 （主處理常式以外的程式碼）。如果您已啟用[佈建並行](provisioned-concurrency.md)，則`Init`階段會在第一次調用期間發生，或在事件函數調用之前發生。

  `Init` 階段分為三個子階段：`Extension init`、`Runtime init` 以及 `Function init`。這些子階段可確保所有擴充功能和執行時間在事件函數程式碼執行之前完成其設定任務。
+ `Invoke`：在此階段中，Lambda 會叫用事件函數處理常式。在事件函數執行到完成之後，Lambda 準備處理另一個事件函數調用。
+ `Shutdown`：如果 Lambda 事件函數在一段時間內未收到任何叫用，就會觸發此階段。在 `Shutdown` 階段中，Lambda 會關閉執行時間、警示擴展功能以便它們完全停止，然後移除環境。Lambda 會傳送 `Shutdown` 事件到每個擴展功能，這會告訴擴展功能環境即將關閉。

每個階段都會從 Lambda 到執行時間和所有已註冊延伸項目的事件開始。執行時間和每個已註冊延伸項目都會透過傳送 `Next` API 請求來表示已完成。當每個處理已完成且沒有擱置的事件時，Lambda 凍結執行環境。

![延伸模組的 Lambda 執行環境生命週期。](https://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/Overview-Full-Sequence.png)


 

**Topics**
+ [初始化階段](#runtimes-extensions-api-reg)
+ [調用階段](#runtimes-lifecycle-extensions-invoke)
+ [關閉階段](#runtimes-lifecycle-extensions-shutdown)
+ [許可與組態](#runtimes-extensions-registration-api-e)
+ [失敗處理](#runtimes-extensions-api-failure)
+ [故障排除延伸項目](#runtimes-extensions-api-trbl)

### 初始化階段
<a name="runtimes-extensions-api-reg"></a>

在 `Extension init` 階段中，每個延伸項目都需要向 Lambda 註冊才能接收事件。Lambda 會使用延伸項目的完整檔案名稱來驗證延伸項目是否已完成啟動程序。因此，每個 `Register` API 呼叫必須包含延伸項目完整檔案名稱的 `Lambda-Extension-Name` 標頭。

您最多可以註冊 10 個 Event Function 擴充功能。此限制會透過 `Register` API 呼叫強制執行。

在每個延伸項目註冊後，Lambda 會啟動 `Runtime init` 階段。執行時間程序會呼叫 `functionInit` 以啟動 `Function init` 階段。

`Init` 階段會在執行階段之後完成，每個已註冊延伸項目都會透過傳送 `Next` API 請求來表示已完成。

**注意**  
延伸項目可以在 `Init` 階段的任何時候完成初始化。

![Lambda Init 階段的事件順序。](https://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/Init-Phase.png)


### 調用階段
<a name="runtimes-lifecycle-extensions-invoke"></a>

呼叫 Lambda 事件函數以回應 `Next` API 請求時，Lambda 會將`Invoke`事件傳送至執行時間，以及針對`Invoke`事件註冊的每個延伸。

**注意**  
**Lambda 受管執行個體：**Lambda 受管執行個體函數的延伸模組無法註冊`Invoke`事件。由於 Lambda 受管執行個體支援單一執行環境中的並行調用，因此不支援該`Invoke`事件。延伸模組只能註冊`Shutdown`事件。如果您需要追蹤調用開始和完成的時間，請透過[遙測 API](telemetry-api.md) 使用`platform.report`平台事件。

在調用期間，外部延伸項目會與事件函數平行執行。它們也會在事件函數完成後繼續執行。您可以使用它來擷取診斷資訊，或將日誌、指標和追蹤傳送到您選擇的位置。

從執行時間收到 Event Function 回應後，Lambda 會將回應傳回給用戶端，即使擴充功能仍在執行中。

`Invoke` 階段會在執行階段後結束，所有延伸項目訊號都透過傳送 `Next` API 請求完成。

![Lambda 調用階段的事件順序。](https://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/Invoke-Phase.png)


**事件承載**：傳送至執行時間 （和 Lambda 事件函數） 的事件會攜帶整個請求、標頭 （例如 `RequestId`) 和承載。傳送至每個延伸項目的事件會包含描述事件內容的中繼資料。此生命週期事件包括事件的類型、事件函數逾時的時間 (`deadlineMs`)、`requestId`、調用的事件函數的 Amazon Resource Name (ARN) 和追蹤標頭。

想要存取 Event Function 事件內文的延伸模組可以使用與延伸模組通訊的執行中 SDK。呼叫 Event Function 時，Event Function 開發人員會使用執行中 SDK 將承載傳送至延伸模組。

以下是承載範例：

```
{
    "eventType": "INVOKE",
    "deadlineMs": 676051,
    "requestId": "3da1f2dc-3222-475e-9205-e2e6c6318895",
    "invokedFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:ExtensionTest",
    "tracing": {
        "type": "X-Amzn-Trace-Id",
        "value": "Root=1-5f35ae12-0c0fec141ab77a00bc047aa2;Parent=2be948a625588e32;Sampled=1"
    }
 }
```

**持續時間限制**：事件函數的逾時設定會限制整個`Invoke`階段的持續時間。例如，如果您將事件函數逾時設定為 360 秒，則事件函數和所有延伸項目都需要在 360 秒內完成。請注意，沒有獨立的調用後階段。持續時間是執行時間和所有擴充功能呼叫完成所需的總時間，而且在事件函數和所有擴充功能完成執行之前都不會計算。

**效能影響和延伸額外負荷**：延伸可能會影響事件函數效能。身為延伸項目的作者，您可以控制延伸項目的效能影響。例如，如果您的延伸模組執行運算密集的操作，事件函數的持續時間會增加，因為延伸模組和事件函數程式碼共用相同的 CPU 資源。此外，如果您的擴充功能在事件函數調用完成後執行廣泛的操作，則事件函數持續時間會增加，因為 `Invoke`階段會繼續，直到所有擴充功能發出訊號為止。

**注意**  
Lambda 會根據事件函數的記憶體設定按比例配置 CPU 功率。您可能會在較低的記憶體設定下看到增加的執行和初始化持續時間，因為事件函數和延伸程序正在競爭相同的 CPU 資源。若要減少執行和初始化持續時間，請嘗試增加記憶體設定。

為了協助識別延伸在 `Invoke` 階段上造成的效能衝擊，Lambda 會輸出 `PostRuntimeExtensionsDuration` 指標。此指標會測量執行階段 `Next` API 請求與上次延伸 `Next` API 請求之間所花費的累計時間。若要測量使用的記憶體增加的情況，請使用 `MaxMemoryUsed` 指標。如需事件函數指標的詳細資訊，請參閱 [將 CloudWatch 指標與 Lambda 搭配使用](monitoring-metrics.md)。

Event Function 開發人員可以並排執行其 Event Functions 的不同版本，以了解特定延伸模組的影響。我們建議延伸模組作者發佈預期的資源耗用，讓 Event Function 開發人員更輕鬆地選擇適當的延伸模組。

### 關閉階段
<a name="runtimes-lifecycle-extensions-shutdown"></a>

當 Lambda 即將關閉執行時間，它會將 `Shutdown` 事件傳送至每個已註冊外部延伸。延伸項目可以使用此時間進行最終清理工作。系統會傳送 `Shutdown` 事件以回應 `Next` API 請求。

**持續時間限制**：`Shutdown` 階段的最長持續時間視已註冊延伸項目的組態而定：
+ 0 毫秒 - 沒有註冊延伸的函數
+ 500 毫秒 - 具有已註冊內部延伸項目的函數
+ 2,000 毫秒 - 具有一個或多個已註冊外部延伸項目的函數

如果執行時間或延伸項目未在限制內回應 `Shutdown` 事件，Lambda 會使用 `SIGKILL` 訊號結束程序。

![Lambda 關機階段的事件順序。](https://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/Shutdown-Phase.png)


**事件承載**：`Shutdown` 事件會包含關閉的原因和剩餘時間 (以毫秒為單位)。

 `shutdownReason` 包含以下值：
+ SPINDOWN - 正常關閉
+ TIMEOUT - 持續時間限制逾時
+ FAILURE - 錯誤條件，例如 `out-of-memory` 事件

```
{ 
  "eventType": "SHUTDOWN", 
  "shutdownReason": "reason for shutdown", 
  "deadlineMs": "the time and date that the function times out in Unix time milliseconds" 
}
```

### 許可與組態
<a name="runtimes-extensions-registration-api-e"></a>

延伸項目會在與 Lambda 事件函數相同的執行環境中執行。延伸項目也會與事件函數共用資源，例如 CPU、記憶體和`/tmp`磁碟儲存。此外，延伸使用與事件函數相同的 AWS Identity and Access Management (IAM) 角色和安全性內容。

**檔案系統和網路存取許可**：延伸項目會在與事件函數執行時間相同的檔案系統和網路命名空間中執行。這表示延伸項目必須與相關的作業系統相容。如果延伸需要任何其他傳出網路流量規則，您必須將這些規則套用至事件函數組態。

**注意**  
由於事件函數程式碼目錄是唯讀的，延伸模組無法修改事件函數程式碼。

**環境變數**：延伸項目可以存取 Event Function [的環境變數](configuration-envvars.md)，但下列執行時間程序特有的變數除外：
+ `AWS_EXECUTION_ENV`
+ `AWS_LAMBDA_LOG_GROUP_NAME`
+ `AWS_LAMBDA_LOG_STREAM_NAME`
+ `AWS_XRAY_CONTEXT_MISSING`
+ `AWS_XRAY_DAEMON_ADDRESS`
+ `LAMBDA_RUNTIME_DIR`
+ `LAMBDA_TASK_ROOT`
+ `_AWS_XRAY_DAEMON_ADDRESS`
+ `_AWS_XRAY_DAEMON_PORT`
+ `_HANDLER`

**注意**  
**偵測 Lambda 受管執行個體：**延伸項目可以檢查`AWS_LAMBDA_INITIALIZATION_TYPE`環境變數，以判斷它們是否在 Lambda 受管執行個體上執行，而不是在 Lambda （預設） 函數上執行。這是擴充功能根據執行環境類型調整其行為的建議方法。

### 失敗處理
<a name="runtimes-extensions-api-failure"></a>

**初始化失敗**：如果延伸失敗，Lambda 會重新啟動執行環境以強制執行一致的行為，並促進延伸項目快速失敗。此外，對於某些客戶，延伸項目必須符合任務關鍵需求，例如日誌、安全性、治理和遙測收集。

**叫用失敗 **（例如記憶體不足、事件函數逾時）：由於延伸項目與執行時間共用資源，記憶體耗盡會影響它們。當執行階段失敗時，所有延伸項目和執行階段本身都會參與此 `Shutdown` 階段。此外，執行時間會自動重新啟動，做為目前調用的一部分，或透過延遲的重新初始化機制。

如果在 期間發生故障 （例如事件函數逾時或執行時間錯誤）`Invoke`，Lambda 服務會執行重設。重設的行為會與 `Shutdown` 事件一樣。首先，Lambda 關閉執行時間，然後將 `Shutdown` 事件傳送給每個已註冊外部延伸項目。事件會包括關閉的原因。如果將此環境用於新的調用，延伸項目和執行階段會重新初始化為下次調用的一部分。

![執行環境範例：Init、Invoke、Invoke with Error、Invoke、Shutdown。](https://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/Overview-Invoke-with-Error.png)


如需上圖更為詳細的說明，請參閱 [調用階段期間出現的故障](lambda-runtime-environment.md#runtimes-lifecycle-invoke-with-errors)。

**延伸項目日誌**：Lambda 會將延伸項目的日誌輸出傳送至 CloudWatch Logs。Lambda 也會在 `Init` 期間為每個延伸項目產生額外的日誌事件。日誌事件會記錄成功時的名稱和註冊偏好設定 (事件、設定)，或失敗時的失敗原因。

### 故障排除延伸項目
<a name="runtimes-extensions-api-trbl"></a>
+ 如果 `Register` 請求失敗，請確定 `Register` API 呼叫中的 `Lambda-Extension-Name` 標頭包含延伸項目的完整檔案名稱。
+ 如果內部延伸項目的 `Register` 請求失敗，請確定請求不會註冊 `Shutdown` 事件。

## Extensions API 參考
<a name="runtimes-extensions-registration-api"></a>

對於 Extensions API 版本 **2020-01-01** 的 OpenAPI 規範可以在這裡找到：[extensions-api.zip](samples/extensions-api.zip)

您可以從 `AWS_LAMBDA_RUNTIME_API` 環境變數擷取 API 端點的值。若要傳送 `Register` 請求，請在每個 API 路徑之前使用前綴 `2020-01-01/`。例如：

```
http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/register 
```

**Topics**
+ [登錄](#extensions-registration-api-a)
+ [下一頁](#extensions-api-next)
+ [初次化錯誤](#runtimes-extensions-init-error)
+ [結束錯誤](#runtimes-extensions-exit-error)

### 登錄
<a name="extensions-registration-api-a"></a>

在 `Extension init` 階段中，所有延伸項目都需要向 Lambda 註冊才能接收事件。Lambda 會使用延伸項目的完整檔案名稱來驗證延伸項目是否已完成啟動程序。因此，每個 `Register` API 呼叫必須包含延伸項目完整檔案名稱的 `Lambda-Extension-Name` 標頭。

執行階段程序會啟動和停止內部延伸項目，因此不允許它們註冊 `Shutdown` 事件。

**路徑** – `/extension/register`

**方法** – **POST**

**請求標頭**
+ `Lambda-Extension-Name` - 延伸項目的完整檔案名稱。必要：是。類型：字串
+ `Lambda-Extension-Accept-Feature` - 用來在註冊期間指定選用的延伸項目特色。必要：否。類型：逗號分隔的字串。可使用此設定來指定的特色：
  + `accountId` – 如果指定，延伸模組註冊回應會包含與您註冊延伸模組的 Lambda 事件函數相關聯的帳戶 ID。

**請求內文參數**
+ `events` - 要註冊的事件陣列。必要：否。類型：字串陣列。有效字串：`INVOKE`、`SHUTDOWN`。
**注意**  
**Lambda 受管執行個體：**Lambda 受管執行個體函數的延伸模組只能註冊`SHUTDOWN`事件。嘗試註冊`INVOKE`事件會導致錯誤。這是因為 Lambda 受管執行個體支援單一執行環境中的並行調用。

**回應標頭**
+ `Lambda-Extension-Identifier` - 產生所有後續請求所需的唯一代理程式識別符 (UUID 字串)。

**回應代碼**
+ 200 - 回應主體包含的函數名稱、函數版本和處理常式名稱。
+ 400 - 錯誤請求
+ 403 - 禁止
+ 500 - 容器錯誤。不可復原的狀態。延伸項目應會立即結束。

**Example 範例請求主體**  

```
{
    'events': [ 'INVOKE', 'SHUTDOWN']
}
```

**Example 範例回應主題**  

```
{
    "functionName": "helloWorld",
    "functionVersion": "$LATEST",
    "handler": "lambda_function.lambda_handler"
}
```

**Example 具有選用 accountId 特色的回應內文範例**  

```
{
    "functionName": "helloWorld",
    "functionVersion": "$LATEST",
    "handler": "lambda_function.lambda_handler",
    "accountId": "123456789012"
}
```

### 下一頁
<a name="extensions-api-next"></a>

延伸項目會傳送 `Next` API 請求以接收下一個事件，可以是 `Invoke` 事件或 `Shutdown` 事件。回應主體包含承載，這是包含事件資料的 JSON 文件。

延伸項目會傳送 `Next` API 請求，以表示它已準備好接收新事件。這是一個封鎖調用。

請勿在 GET 調用上設定逾時，因為延伸項目可以暫停一段時間，直到有事件傳回為止。

**路徑** – `/extension/event/next`

**方法** – **GET**

**請求標頭**
+ `Lambda-Extension-Identifier` - 延伸項目的唯一識別符 (UUID 字串)。必要：是。類型：UUID 字串。

**回應標頭**
+ `Lambda-Extension-Event-Identifier` - 延伸項目的唯一識別符 (UUID 字串)。

**回應代碼**
+ 200 - 回應包含下個事件 (`EventInvoke` 或 `EventShutdown`) 的相關資訊。
+ 403 - 禁止
+ 500 - 容器錯誤。不可復原的狀態。延伸項目應會立即結束。

### 初次化錯誤
<a name="runtimes-extensions-init-error"></a>

延伸項目會使用此方法向 Lambda 報告初始化錯誤。當延伸項目註冊後無法初始化時會調用它。Lambda 收到錯誤後，進一步的 API 呼叫沒有成功。延伸項目應該在收到 Lambda 的回應之後退出。

**路徑** – `/extension/init/error`

**方法** – **POST**

**請求標頭**
+ `Lambda-Extension-Identifier` - 延伸項目的唯一識別符。必要：是。類型：UUID 字串。
+ `Lambda-Extension-Function-Error-Type` - 擴展遇到的錯誤類型。必要：是。此標頭包含一個字串值。Lambda 可接受任何字串，但我們建議使用格式 <category.reason>。例如：
  + Extension.NoSuchHandler
  + Extension.APIKeyNotFound
  + Extension.ConfigInvalid
  + Extension.UnknownReason

**請求內文參數**
+ `ErrorRequest` - 關於錯誤的資訊。必要：否。

此欄位是具有下列結構的 JSON 物件：

```
{
      errorMessage: string (text description of the error),
      errorType: string,
      stackTrace: array of strings
}
```

請注意，Lambda 接受 `errorType` 的任何值。

下列範例顯示 Lambda 函數錯誤訊息，其中函數無法剖析調用中提供的事件資料。

**Example 函數錯誤**  

```
{
      "errorMessage" : "Error parsing event data.",
      "errorType" : "InvalidEventDataException",
      "stackTrace": [ ]
}
```

**回應代碼**
+ 202 - 已接受
+ 400 - 錯誤請求
+ 403 - 禁止
+ 500 - 容器錯誤。不可復原的狀態。延伸項目應會立即結束。

### 結束錯誤
<a name="runtimes-extensions-exit-error"></a>

延伸項目會使用此方法，在結束前向 Lambda 報告錯誤。當您遇到意外失敗時呼叫它。Lambda 收到錯誤後，進一步的 API 呼叫沒有成功。延伸項目應該在收到 Lambda 的回應之後退出。

**路徑** – `/extension/exit/error`

**方法** – **POST**

**請求標頭**
+ `Lambda-Extension-Identifier` - 延伸項目的唯一識別符。必要：是。類型：UUID 字串。
+ `Lambda-Extension-Function-Error-Type` - 擴展遇到的錯誤類型。必要：是。此標頭包含一個字串值。Lambda 可接受任何字串，但我們建議使用格式 <category.reason>。例如：
  + Extension.NoSuchHandler
  + Extension.APIKeyNotFound
  + Extension.ConfigInvalid
  + Extension.UnknownReason

**請求內文參數**
+ `ErrorRequest` - 關於錯誤的資訊。必要：否。

此欄位是具有下列結構的 JSON 物件：

```
{
      errorMessage: string (text description of the error),
      errorType: string,
      stackTrace: array of strings
}
```

請注意，Lambda 接受 `errorType` 的任何值。

下列範例顯示 Lambda 函數錯誤訊息，其中函數無法剖析調用中提供的事件資料。

**Example 函數錯誤**  

```
{
      "errorMessage" : "Error parsing event data.",
      "errorType" : "InvalidEventDataException",
      "stackTrace": [ ]
}
```

**回應代碼**
+ 202 - 已接受
+ 400 - 錯誤請求
+ 403 - 禁止
+ 500 - 容器錯誤。不可復原的狀態。延伸項目應會立即結束。

 