

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

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

Lambda 函數作者使用延伸項目將 Lambda 與其偏好的監控、可觀度、安全性和治理工具整合在一起。函數作者可以使用來自 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 參考。

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/telemetry-api-concept-diagram.png)


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

延伸項目會在執行環境中作為獨立的處理序執行，並在完全處理函數調用之後繼續執行。由於延伸項目會以程序執行，因此您可以使用與函數不同的語言來撰寫。我們建議您使用編譯語言實作延伸項目。在這種情況下，延伸項目是獨立的二進位檔案，會與支援的執行時間相容。所有 [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 會使用設定的資源建立或解除凍結執行環境，下載函數程式碼和所有層，初始化所有擴展功能，初始化執行時間，然後執行函數的初始化程式碼 (主處理常式之外的程式碼)。此 `Init` 階段發生在第一次調用期間，或者在函數調用之前發生 (如果您已啟用[佈建並行](provisioned-concurrency.md))。

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

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

![\[\]](http://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 個延伸項目。此限制會透過 `Register` API 呼叫強制執行。

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

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

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

![\[\]](http://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`平台事件。

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

從執行時間中收到函數回應之後，即使延伸項目仍在執行中，Lambda 也會將回應傳回給用戶端。

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

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/Invoke-Phase.png)


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

想要存取函式事件主體的延伸項目，您可以使用與延伸項目通訊的執行階段 SDK。函式開發人員會使用執行階段內 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)。

函式開發人員可以並排執行不同版本的函式，以了解特定延伸項目的影響。我們建議延伸項目作者發佈預期的資源消耗，以便函式開發人員更容易選擇合適的延伸項目。

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

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

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

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

![\[\]](http://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) 角色和安全性內容。

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

**注意**  
由於函式程式碼目錄是唯讀的目錄，因此延伸項目無法修改函式程式碼。

**環境變數**：延伸項目可以存取函式的[環境變數](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` 事件傳送給每個已註冊外部延伸項目。事件會包括關閉的原因。如果將此環境用於新的調用，延伸項目和執行階段會重新初始化為下次調用的一部分。

![\[執行環境範例：初始化、調用、調用出現錯誤、調用、關閉\]](http://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 - 容器錯誤。不可復原的狀態。延伸項目應會立即結束。

 