

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

# 使用 Lambda 函數作為 Application Load Balancer 的目標
<a name="lambda-functions"></a>

您可以將 Lambda 函數註冊為目標，並設定接聽程式規則，將請求轉送到 Lambda 函數的目標群組。當負載平衡器將請求轉送到使用 Lambda 函數做為目標的目標群組時，它會呼叫您的 Lambda 函數，並將請求的內容以 JSON 格式傳遞至 Lambda 函數。

負載平衡器會直接叫用 Lambda 函數，而不是使用網路連線。因此，Application Load Balancer 安全群組的傳出規則沒有要求。

**限制**
+ Lambda 函數和目標群組必須在相同的帳戶中，且在相同的區域內。
+ 您可以傳送到 Lambda 函數之請求內文的大小上限是 1 MB。如需相關的大小限制，請參閱 [HTTP header limits](https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/how-elastic-load-balancing-works.html#http-header-limits)。
+ Lambda 函數可以傳送的回應 JSON 的大小上限是 1 MB。
+ 不支援 WebSocket。升級請求會被拒絕，出現 HTTP 400 代碼。
+ 不支援 Local Zone。
+ 不支援自動目標權重 (ATW)。

**Topics**
+ [準備 Lambda 函數](#prepare-lambda-function)
+ [為 Lambda 函數建立目標群組](#create-lambda-target-group)
+ [從負載平衡器接收事件](#receive-event-from-load-balancer)
+ [對負載平衡器進行回應](#respond-to-load-balancer)
+ [多值標頭](#multi-value-headers)
+ [啟用運作狀態檢查](#enable-health-checks-lambda)
+ [註冊 Lambda 函數](#register-lambda-function)
+ [取消註冊 Lambda 函數](#deregister-lambda-function)

如需示範，請參閱 [Lambda Target on Application Load Balancer](https://exampleloadbalancer.com/lambda_demo.html)。

## 準備 Lambda 函數
<a name="prepare-lambda-function"></a>

如果將 Lambda 函數與 Application Load Balancer 搭配使用，請採用下列建議。

**調用 Lambda 函數的許可**  
如果您使用 AWS 管理主控台來建立目標群組和註冊 Lambda 函數，主控台會代表您將所需許可新增至 Lambda 函數政策。否則，在建立目標群組並使用 註冊函數之後 AWS CLI，您必須使用 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令授予 Elastic Load Balancing 調用 Lambda 函數的許可。我們建議您使用 `aws:SourceAccount` 和 `aws:SourceArn` 條件索引鍵來將函數調用限制在指定的目標群組。如需詳細資訊，請參閱《IAM 使用者指南》**中的[混淆代理人問題](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html)。

```
aws lambda add-permission \
    --function-name lambda-function-arn-with-alias-name \ 
    --statement-id elb1 \
    --principal elasticloadbalancing.amazonaws.com \
    --action lambda:InvokeFunction \
    --source-arn target-group-arn \
    --source-account target-group-account-id
```

**Lambda 函數版本控制**  
您可以為每個目標群組註冊一個 Lambda 函數。為了確保您可以變更 Lambda 函數，且負載平衡器一律會呼叫目前版本的 Lambda 函數，請建立一個函數別名，並將該別名包含在向負載平衡器註冊 Lambda 函數時的函數 ARN 中。如需詳細資訊，請參閱《 *AWS Lambda 開發人員指南*》中的[AWS Lambda 函數別名](https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html)。

**函數逾時**  
負載平衡器會等待直到您的 Lambda 函數回應或逾時。建議您根據您預期的執行時間來設定 Lambda 函數逾時。如需預設逾時值及其變更方式的相關資訊，請參閱[設定 Lambda 函數逾時](https://docs.aws.amazon.com/lambda/latest/dg/configuration-timeout.html)。如需您可以設定的逾時值上限的相關資訊，請參閱[AWS Lambda 配額](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html)。

## 為 Lambda 函數建立目標群組
<a name="create-lambda-target-group"></a>

建立目標群組以用於請求路由。如果請求內容符合某接聽程式規則，內含會將它轉送到此目標群組的動作，則負載平衡器會呼叫註冊的 Lambda 函數。

------
#### [ Console ]

**建立目標群組和註冊 Lambda 函數**

1. 前往 [https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/) 開啟 Amazon EC2 主控台。

1. 在導覽窗格的 **Load Balancing** (負載平衡) 中，選擇 **Target Groups** (目標群組)。

1. 選擇 **Create target group (建立目標群組)**。

1. 在**選取目標類型**中，選取 **Lambda 函數**。

1. 針對 **Target group name** (目標群組名稱)，輸入目標群組的名稱。

1. (選用) 若要啟用運作狀態檢查，請選擇**運作狀態檢查**區段中的**啟用**。

1. （選用） 展開**標籤**。針對每個標籤，選擇**新增標籤**，然後輸入標籤索引鍵和標籤值。

1. 選擇**下一步**。

1. 如果您準備好註冊 Lambda 函數，請選擇**選取 Lambda 函數**，然後從清單中選擇 Lambda 函數，或選擇**輸入 Lambda 函數 ARN**，然後輸入 Lambda 函數的 ARN。

   如果您尚未準備好註冊 Lambda 函數，**請稍後選擇註冊 Lambda 函數**，稍後再註冊目標。如需詳細資訊，請參閱[登記目標](target-group-register-targets.md#register-targets)。

1. 選擇 **Create target group (建立目標群組)**。

------
#### [ AWS CLI ]

**建立 類型的目標群組 lambda**  
使用 [create-target-group](https://docs.aws.amazon.com/cli/latest/reference/elbv2/create-target-group.html) 命令。

```
aws elbv2 create-target-group \
    --name my-target-group \
    --target-type lambda
```

**註冊 Lambda 函數**  
使用 [register-targets](https://docs.aws.amazon.com/cli/latest/reference/elbv2/register-targets.html) 命令。

```
aws elbv2 register-targets \
    --target-group-arn target-group-arn \
    --targets Id=lambda-function-arn
```

------
#### [ CloudFormation ]

**建立目標群組和註冊 Lambda 函數**  
定義 [AWS::ElasticLoadBalancingV2::TargetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html) 類型的資源。如果您現在尚未準備好註冊 Lambda 函數，您可以省略 `Targets` 屬性，稍後再將其新增。

```
Resources:
  myTargetGroup:
    Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
    Properties:
      Name: my-target-group
      TargetType: lambda
      Tags: 
        - Key: 'department'
          Value: '123'
      Targets:
        - Id: !Ref myLambdaFunction
```

------

## 從負載平衡器接收事件
<a name="receive-event-from-load-balancer"></a>

負載平衡器同時支援透過 HTTP 和 HTTPS 的請求進行 Lambda 呼叫。負載平衡器會以 JSON 格式傳送事件。負載平衡器會將以下標頭新增至每個請求：`X-Amzn-Trace-Id`、`X-Forwarded-For`、`X-Forwarded-Port` 和 `X-Forwarded-Proto`。

如果 `content-encoding` 標頭存在，負載平衡器 Base64 會對內文使用 Base64 編碼並將 `isBase64Encoded` 設定為 `true`。

如果 `content-encoding` 標頭不存在，則 Base64 編碼取決於內容類型。如果是以下類型，負載平衡器會依原樣傳送內文並將 `isBase64Encoded` 設定為 `false`：text/\$1、application/json、application/javascript 和 application/xml。否則，負載平衡器會對內文使用 Base64 編碼，並將 `isBase64Encoded` 設定為 `true`。

以下為範例 事件。

```
{
    "requestContext": {
        "elb": {
            "targetGroupArn": "arn:aws:elasticloadbalancing:region:123456789012:targetgroup/my-target-group/6d0ecf831eec9f09"
        }
    },
    "httpMethod": "GET",
    "path": "/",
    "queryStringParameters": {parameters},
    "headers": {
        "accept": "text/html,application/xhtml+xml",
        "accept-language": "en-US,en;q=0.8",
        "content-type": "text/plain",
        "cookie": "cookies",
        "host": "lambda-846800462-us-east-2.elb.amazonaws.com",
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)",
        "x-amzn-trace-id": "Root=1-5bdb40ca-556d8b0c50dc66f0511bf520",
        "x-forwarded-for": "72.21.198.66",
        "x-forwarded-port": "443",
        "x-forwarded-proto": "https"
    },
    "isBase64Encoded": false,
    "body": "request_body"
}
```

## 對負載平衡器進行回應
<a name="respond-to-load-balancer"></a>

來自 Lambda 函數的回應必須包含 Base64 編碼狀態、狀態碼、狀態描述和標頭。您可以省略內文。

若要在回應的內文中包含二進位內容，您必須將內容以 Base64 編碼，並將 `isBase64Encoded` 設定為 `true`。負載平衡器會解碼內容，以擷取二進位內容，並將其傳送至 HTTP 回應內文中的用戶端。

負載平衡器並不遵守按躍點的標頭，例如 `Connection` 或 `Transfer-Encoding`。您可以省略 `Content-Length` 標頭，因為負載平衡器會在將回應傳送至用戶端之前計算。

以下是來自基於 Lambda 函數的 **nodejs** 的範例回應。

```
{
    "isBase64Encoded": false,
    "statusCode": 200,
    "statusDescription": "200 OK",
    "headers": {
        "Set-cookie": "cookies",
        "Content-Type": "application/json"
    },
    "body": "Hello from Lambda (optional)"
}
```

若是與​搭配 Application Load Balancer 使用的 Lambda 函數範本，相關資訊請至 GitHub 參閱 [application-load-balancer-serverless-app](https://github.com/aws/elastic-load-balancing-tools/tree/master/application-load-balancer-serverless-app)。或者，開啟 [Lambda 主控台](https://console.aws.amazon.com/lambda)，選擇**應用程式**、**建立應用程式**，然後從 AWS Serverless Application Repository中選取下列其中一項：
+ ALB-Lambda-Target-UploadFiletoS3
+ ALB-Lambda-Target-BinaryResponse
+ ALB-Lambda-Target-WhatisMyIP

## 多值標頭
<a name="multi-value-headers"></a>

如果來自用戶端的請求或來自 Lambda 函數的回應，包含具有多個值的標頭或包含相同標頭多次，或查詢參數具有多個值的相同索引鍵，您可以啟用對多值標頭語法的支援。啟用多值標頭之後，負載平衡器和 Lambda 函數之間交換的標頭和查詢參數會使用陣列而不是字串。如果您未啟用多值標頭語法，且標頭或查詢參數具有多個值，負載平衡器會使用它接收的最後一個值。

**Topics**
+ [具有多值標頭的請求](#multi-value-headers-request)
+ [具有多值標頭的回應](#multi-value-headers-response)
+ [啟用多值標頭](#enable-multi-value-headers)

### 具有多值標頭的請求
<a name="multi-value-headers-request"></a>

根據您是否為目標群組啟用多值標頭而定，用於標頭和查詢字串參數的欄位名稱有所不同。

以下範例請求具有使用相同金鑰的兩個查詢參數：

```
http://www.example.com?&myKey=val1&myKey=val2
```

採用預設格式時，負載平衡器會使用用戶端傳送的最後一個值，並使用 `queryStringParameters` 向您傳送包含查詢字串參數的事件。例如：

```
"queryStringParameters": { "myKey": "val2"},
```

如果您啟用多值標頭，負載平衡器會使用用戶端傳送的兩個金鑰值，並使用 `multiValueQueryStringParameters` 向您傳送包含查詢字串參數的事件。例如：

```
"multiValueQueryStringParameters": { "myKey": ["val1", "val2"] },
```

同樣地，假設用戶端會傳送的請求標頭中具有兩個 Cookie：

```
"cookie": "name1=value1",
"cookie": "name2=value2",
```

採用預設格式時，負載平衡器會使用用戶端傳送的最後一個 Cookie，並使用 `headers` 向您傳送包含標頭的事件。例如：

```
"headers": {
    "cookie": "name2=value2",
    ...
},
```

如果您啟用多值標頭，負載平衡器會使用用戶端傳送的兩個 Cookie，並使用 `multiValueHeaders` 向您傳送包含標頭的事件。例如：

```
"multiValueHeaders": {
    "cookie": ["name1=value1", "name2=value2"],
    ...
},
```

如果查詢參數是 URL 編碼，負載平衡器不會進行解碼。您必須在 Lambda 函數中解碼。

### 具有多值標頭的回應
<a name="multi-value-headers-response"></a>

根據您是否為目標群組啟用多值標頭而定，用於標頭的欄位名稱有所不同。如果您已啟用多重值標頭和 `headers`，您必須使用 `multiValueHeaders`。

使用預設格式，您可以指定單一 Cookie：

```
{
  "headers": {
      "Set-cookie": "cookie-name=cookie-value;Domain=myweb.com;Secure;HttpOnly",
      "Content-Type": "application/json"
  },
}
```

如果您啟用多值標頭，您必須如下所示指定多個 Cookie：

```
{
  "multiValueHeaders": {
      "Set-cookie": ["cookie-name=cookie-value;Domain=myweb.com;Secure;HttpOnly","cookie-name=cookie-value;Expires=May 8, 2019"],
      "Content-Type": ["application/json"]
  },
}
```

負載平衡器可能會依照與 Lambda 回應承載中指定順序不同的順序將標頭傳送到用戶端。因此，不要指望標頭會以特定順序返回。

### 啟用多值標頭
<a name="enable-multi-value-headers"></a>

您可以為具有目標類型 `lambda` 的目標群組啟用或停用多值標頭。

------
#### [ Console ]

**啟用多值標頭**

1. 前往 [https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/) 開啟 Amazon EC2 主控台。

1. 在導覽窗格的 **Load Balancing** (負載平衡) 中，選擇 **Target Groups (目標群組)**。

1. 選擇目標群組的名稱，以開啟其詳細資訊頁面。

1. 在**屬性**索引標籤中，選擇**編輯**。

1. 啟用**多值標頭**。

1. 選擇**儲存變更**。

------
#### [ AWS CLI ]

**啟用多值標頭**  
使用 [modify-target-group-attributes](https://docs.aws.amazon.com/cli/latest/reference/elbv2/modify-target-group-attributes.html) 命令搭配 `lambda.multi_value_headers.enabled` 屬性。

```
aws elbv2 modify-target-group-attributes \
    --target-group-arn target-group-arn \
    --attributes "Key=lambda.multi_value_headers.enabled,Value=true"
```

------
#### [ CloudFormation ]

**啟用多值標頭**  
更新 [AWS::ElasticLoadBalancingV2::TargetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html) 資源以包含 `lambda.multi_value_headers.enabled` 屬性。

```
Resources:
  myTargetGroup:
    Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
    Properties:
      Name: my-target-group
      TargetType: lambda
      Tags: 
        - Key: 'department'
          Value: '123'
      Targets:
        - Id: !Ref myLambdaFunction
      TargetGroupAttributes:
        - Key: "lambda.multi_value_headers.enabled"
          Value: "true"
```

------

## 啟用運作狀態檢查
<a name="enable-health-checks-lambda"></a>

在預設情況下，會為類型 `lambda` 的目標群組停用運作狀態檢查。您可以啟用運作狀態檢查，以便使用 Amazon Route 53 來實作 DNS 備援。Lambda 函數可以檢查下游服務的運作狀態，之後再回應運作狀態檢查的請求。如果來自 Lambda 函數的回應指出運作狀態檢查失敗，則會將運作狀態檢查失敗傳遞至 Route 53。您可以設定 Route 53 以容錯移轉到備用的應用程式堆疊。

將向您就任何 Lambda 函數呼叫而進行的運作狀態檢查收費。

以下是傳送到 Lambda 函數的運作狀態檢查事件格式。若要檢查事件是否為運作狀態檢查事件，請檢查 user-agent 欄位的值。運作狀態檢查的使用者代理程式為 `ELB-HealthChecker/2.0`。

```
{
    "requestContext": {
        "elb": {
            "targetGroupArn": "arn:aws:elasticloadbalancing:region:123456789012:targetgroup/my-target-group/6d0ecf831eec9f09"
        }
    },
    "httpMethod": "GET",  
    "path": "/",  
    "queryStringParameters": {},  
    "headers": {
        "user-agent": "ELB-HealthChecker/2.0"
    },  
    "body": "",  
    "isBase64Encoded": false
}
```

------
#### [ Console ]

**啟用lambda目標群組的運作狀態檢查**

1. 前往 [https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/) 開啟 Amazon EC2 主控台。

1. 在導覽窗格的 **Load Balancing** (負載平衡) 中，選擇 **Target Groups (目標群組)**。

1. 選擇目標群組的名稱，以開啟其詳細資訊頁面。

1. 在 **Health checks (運作狀態檢查)** 標籤上，選擇 **Edit (編輯)**。

1. 在**運作狀態檢查**中，選取**啟用**。

1. （選用） 視需要更新運作狀態檢查設定。

1. 選擇**儲存變更**。

------
#### [ AWS CLI ]

**啟用lambda目標群組的運作狀態檢查**  
使用 [modify-target-group](https://docs.aws.amazon.com/cli/latest/reference/elbv2/modify-target-group.html) 命令。

```
aws elbv2 modify-target-group \
    --target-group-arn target-group-arn \
    --health-check-enabled
```

------
#### [ CloudFormation ]

**啟用lambda目標群組的運作狀態檢查**  
更新 [AWS::ElasticLoadBalancingV2::TargetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html) 資源。

```
Resources:
  myTargetGroup:
    Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
    Properties:
      Name: my-target-group
      TargetType: lambda
      HealthCheckEnabled: true
      Tags: 
        - Key: 'department'
          Value: '123'
      Targets:
        - Id: !Ref myLambdaFunction
```

------

## 註冊 Lambda 函數
<a name="register-lambda-function"></a>

您可以在每個目標群組中註冊單一 Lambda 函數。若要取代 Lambda 函數，建議您建立新的目標群組、向新目標群組註冊新函數，以及更新接聽程式規則以使用新的目標群組。

------
#### [ Console ]

**取消註冊 Lambda 函數**

1. 前往 [https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/) 開啟 Amazon EC2 主控台。

1. 在導覽窗格的 **Load Balancing** (負載平衡) 中，選擇 **Target Groups (目標群組)**。

1. 選擇目標群組的名稱，以開啟其詳細資訊頁面。

1. 在**目標**索引標籤上，如果沒有註冊 Lambda 函數，請選擇**註冊目標**。

1. 選取 Lambda 函數或輸入其 ARN。

1. 選擇**註冊**。

------
#### [ AWS CLI ]

**取消註冊 Lambda 函數**  
使用 [register-targets](https://docs.aws.amazon.com/cli/latest/reference/elbv2/register-targets.html) 命令。

```
aws elbv2 register-targets \
    --target-group-arn target-group-arn \
    --targets Id=lambda-function-arn
```

------
#### [ CloudFormation ]

**取消註冊 Lambda 函數**  
更新 [AWS::ElasticLoadBalancingV2::TargetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html) 資源。

```
Resources:
  myTargetGroup:
    Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
    Properties:
      Name: my-target-group
      TargetType: lambda
      Tags: 
        - Key: 'department'
          Value: '123'
      Targets:
        - Id: !Ref myLambdaFunction
```

------

## 取消註冊 Lambda 函數
<a name="deregister-lambda-function"></a>

如果您不再需要將流量傳送到您的 Lambda 函數，則可以將它取消註冊。取消註冊 Lambda 函數之後，傳輸中的請求會失敗，出現 HTTP 5XX 錯誤。

若要取代 Lambda 函數，建議您建立新的目標群組、向新目標群組註冊新函數，以及更新接聽程式規則以使用新的目標群組。

------
#### [ Console ]

**取消註冊 Lambda 函數**

1. 前往 [https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/) 開啟 Amazon EC2 主控台。

1. 在導覽窗格的 **Load Balancing** (負載平衡) 中，選擇 **Target Groups (目標群組)**。

1. 選擇目標群組的名稱，以開啟其詳細資訊頁面。

1. 在**目標**索引標籤上，選取目標，然後選擇**取消註冊**。

1. 出現確認的提示時，請選擇**取消註冊**。

------
#### [ AWS CLI ]

**取消註冊 Lambda 函數**  
使用 [deregister-targets](https://docs.aws.amazon.com/cli/latest/reference/elbv2/deregister-targets.html) 命令。

```
aws elbv2 deregister-targets \
    --target-group-arn target-group-arn \
    --targets Id=lambda-function-arn
```

------