

# Lambda 中的 Apache Kafka 事件轮询器扩展模式
<a name="kafka-scaling-modes"></a>

您可以为 Amazon MSK 和自托管式 Apache Kafka 事件源映射选择两种事件轮询器扩展模式之一：
+ [按需模式（默认）](#kafka-default-mode)
+ [预置模式](#kafka-provisioned-mode)

## 按需模式（默认）
<a name="kafka-default-mode"></a>

当您最初创建 Kafka 事件源时，Lambda 会分配默认数量的事件轮询器来处理 Kafka 主题中的所有分区。Lambda 根据消息负载自动扩展或缩减[事件轮询器](invocation-eventsourcemapping.md#invocation-eventsourcemapping-provisioned-mode)的数量。

Lambda 会按一分钟的间隔时间来评估主题中所有分区的偏移滞后。如果偏移延迟太高，则分区接收消息的速度比 Lambda 处理消息的速度更快。如有必要，Lambda 会在主题中添加或删除事件轮询器。添加或删除事件轮询器的自动扩缩过程在评估后的三分钟内发生。

如果目标 Lambda 函数受到限制，Lambda 会减少事件轮询器的数量。此操作通过减少事件轮询器可以检索和发送到函数的消息数来减少函数的工作负载。

## 预置模式
<a name="kafka-provisioned-mode"></a>

对于需要微调事件源映射吞吐量的工作负载，您可以使用预调配模式。在预调配模式下，您可以为预调配事件轮询器数量定义最小和最大限制。这些预调配事件轮询器专用于事件源映射，并且可以通过响应式自动扩缩处理意外的消息激增。对于具有严格性能要求的 Kafka 工作负载，我们建议您使用预调配模式。

在 Lambda 中，事件轮询器是一种计算单元，其吞吐能力因事件源类型的不同而有所差异。对于 Amazon MSK 和自行管理的 Apache Kafka，每个事件轮询器最多可以处理 5 MB/秒的吞吐量或最多 5 次并发调用。例如，如果您的事件源平均生成 1MB 的有效载荷，而您的函数平均运行时间为 1 秒，则单一的 Kafka 事件轮询器能够支持每秒 5MB 的吞吐量以及 5 次并发的 Lambda 调用（假设没有有效载荷的转换操作）。对于 Amazon SQS，每个事件轮询器最多可以处理 1 MB/秒的吞吐量或最多 10 次并发调用。使用预置模式会产生额外成本，具体取决于您的事件轮询器使用情况。有关定价的详细信息，请参阅 [Amazon Lambda 定价](https://www.amazonaws.cn/lambda/pricing/)。

**注意**  
使用预调配模式时，您无需创建 Amazon PrivateLink VPC 端点或在网络配置过程中授予关联权限。

在预调配模式下，最小事件轮询器数量 (`MinimumPollers`) 的可接受值范围介于 1 到 200 之间（含首尾）。事件轮询器的最大数量 (`MaximumPollers`) 的可接受值范围介于 1 到 2000 之间（含首尾）。`MaximumPollers` 必须大于或等于 `MinimumPollers`。此外，为了保持分区内的有序处理，Lambda 會将 `MaximumPollers` 限制为主题中的分区数量。

有关选择适当的最小和最大事件轮询器值的更多详细信息，请参阅[最佳实践](#kafka-provisioned-mode-bp)。

您可以使用控制台或 Lambda API 为 Kafka 事件源映射配置预调配模式。

**为现有的事件源映射配置预调配模式（控制台）**

1. 打开 Lamba 控制台的 [Functions](https://console.amazonaws.cn/lambda/home#/functions)（函数）页面。

1. 选择具有要为其配置预调配模式的事件源映射的函数。

1. 选择**配置**，然后选择**触发器**。

1. 选择要为其配置预调配模式的事件源映射，然后选择**编辑**。

1. 在**预置模式下**，选择**配置**。
   + 对于**最少事件轮询器**，输入介于 1 到 200 之间的值。如果未指定值，则 Lambda 将选择默认值 1。
   + 对于**最大事件轮询器**，输入介于 1 到 2000 之间的值。此值必须大于或等于**最少事件轮询器**的值。如果未指定值，则 Lambda 将选择默认值 200。

1. 选择**保存**。

您可以使用 [EventSourceMappingConfiguration](https://docs.amazonaws.cn/lambda/latest/api/API_EventSourceMappingConfiguration.html) 中的 [ProvisionedPollerConfig](https://docs.amazonaws.cn/lambda/latest/api/API_ProvisionedPollerConfig.html) 对象，以编程方式配置预调配模式。例如，以下 [UpdateEventSourceMapping](https://docs.amazonaws.cn/lambda/latest/api/API_UpdateEventSourceMapping.html) CLI 命令将 `MinimumPollers` 值配置为 5，将 `MaximumPollers` 值配置为 100。

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --provisioned-poller-config '{"MinimumPollers": 5, "MaximumPollers": 100}'
```

配置预调配模式后，您可以通过监控 `ProvisionedPollers` 指标来观测事件轮询器对您的工作负载的使用情况。有关更多信息，请参阅 [事件源映射指标](monitoring-metrics-types.md#event-source-mapping-metrics)。

要禁用预调配模式并返回默认（按需）模式，您可以使用以下 [UpdateEventSourceMapping](https://docs.amazonaws.cn/lambda/latest/api/API_UpdateEventSourceMapping.html) CLI 命令：

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --provisioned-poller-config '{}'
```

## 高级错误处理和性能功能
<a name="services-kafka-advanced-features"></a>

对于启用了预置模式的 Kafka 事件源映射，您可以配置其他功能来改进错误处理和性能：
+ [重试配置](kafka-retry-configurations.md)：通过最大重试尝试次数、记录期限限制、批次拆分和部分批次响应来控制 Lambda 处理失败记录的方式。
+ [Kafka 失败时的目标](kafka-on-failure-destination.md)：将失败的记录发送到 Kafka 主题以供日后处理或分析。

## 使用预调配模式时的最佳实践和注意事项
<a name="kafka-provisioned-mode-bp"></a>

事件源映射的最小和最大事件轮询器的最佳配置取决于应用程序的性能需求。建议您从默认最小事件轮询器开始，以设定性能配置文件的基准。根据观测到的消息处理模式和所需的性能配置文件调整配置。

对于流量激增且性能需求严格的工作负载，请增加最少的事件轮询器数以处理消息突然激增。要确定所需的最少事件轮询器数，请考虑工作负载的每秒消息数和平均有效载荷大小，并使用单个事件轮询器的吞吐能力（最高 5 Mbps）作为参考。

为了保持分区内的有序处理，Lambda 会将最大事件轮询器数限制为主题中的分区数量。此外，您的事件源映射可以扩展到的最大事件轮询器数取决于函数的并发设置。

激活预调配模式时，更新您的网络设置以删除 Amazon PrivateLink VPC 端点和关联的权限。

## 预置模式的成本优化
<a name="kafka-cost-optimization"></a>

### 预置模式定价
<a name="kafka-provisioned-pricing"></a>

预置模式的计费依据的是预置的最低事件轮询器数量，以及自动扩缩过程中所消耗的事件轮询器数量。费用通过名为事件轮询单元（EPU）的计费单位计算。您需根据所使用的 EPU 数量及使用时长进行付费，其计算单位为“事件轮询单元小时”。您可以将预置模式与单个 ESM 一起用于性能敏感型应用程序，也可以将多个 ESM 分组到同一个 VPC 中以共享 EPU 容量和成本。我们将深入探讨两项可帮助您优化预置模式成本的功能。有关定价的详细信息，请参阅 [Amazon Lambda 定价](https://www.amazonaws.cn/lambda/pricing/)。

### 增强型 EPU 利用率
<a name="kafka-enhanced-epu-utilization"></a>

每个 EPU 支持最高 20 MB/s 的事件轮询吞吐能力，并且默认支持 10 个事件轮询器。当您通过设置最小和最大轮询器数量来为 Kafka ESM 创建预置模式时，它会依据每个 EPU 默认配备 10 个事件轮询器这一标准，使用最小轮询器数量来预置 EPU。但是，每个事件轮询器可以独立扩展以最高支持 5 MB/s 的吞吐能力，这可能意味着在特定的 EPU 上需要较少数量的事件轮询器，并且可能会触发 EPU 的扩展。在 EPU 上分配的事件轮询器数量取决于每个事件轮询器所消耗的计算容量。这种提高 EPU 利用率的方法使得具有不同吞吐量需求的事件轮询器能够有效地利用 EPU 容量，从而降低了所有 ESM 的成本。

### ESM 分组
<a name="kafka-esm-grouping-cost"></a>

为了进一步优化您的预置模式成本，您可以将多个 Kafka ESM 进行分组以共享 EPU 容量。借助 ESM 分组和增强的 EPU 利用率，与仅使用单个 ESM 模式运行相比，对于低吞吐量的工作负载，您能够将预置模式成本最高降低 90%。所有需要少于 1 个 EPU 容量的 ESM 都将受益于 ESM 分组。此类 ESM 通常仅需极少的最小事件轮询器数量即可满足其吞吐量需求。此功能将使您能够将预置模式应用于您所有的 Kafka 工作负载，并受益于诸如模式验证、对 Avro/Protobuf 事件的筛选、低延迟调用以及仅在预置模式下才具备的增强型错误处理等功能。

当您为同一 Amazon VPC 中的多个 ESM 配置具有相同值的 `PollerGroupName` 参数时，这些 ESM 将共享 EPU 资源，而不是每个 ESM 都需要专用 EPU 容量。对于每个轮询器组，最多可以对 100 个 ESM 进行分组，并且一个组中所有 ESM 的聚合最大轮询器数不能超过 2000。

#### 要配置 ESM 分组（控制台）
<a name="kafka-esm-grouping-console-cost"></a>

1. 打开 Lamba 控制台的[函数](https://console.amazonaws.cn/lambda/home#/functions)页面。

1. 选择您的函数。

1. 选择**配置**，然后选择**触发器**。

1. 创建新的 Kafka 事件源映射或编辑现有的 Kafka 事件源映射时，请在**预置模式**下选择**配置**。

1. 对于**最少事件轮询器**，输入介于 1 到 200 之间的值。

1. 对于**最大事件轮询器**，输入介于 1 到 2000 之间的值。

1. 对于**轮询器组名称**，输入组的标识符。对于想要组合在一起的其他 ESM，请使用相同的名称。

1. 选择**保存**。

#### 要配置 ESM 分组（Amazon CLI）
<a name="kafka-esm-grouping-cli-cost"></a>

以下示例创建具有名为 `production-app-group` 的轮询器组的 ESM。

```
aws lambda create-event-source-mapping \
  --function-name myFunction1 \
  --event-source-arn arn:aws:kafka:us-east-1:123456789012:cluster/MyCluster/abcd1234 \
  --topics topic1 \
  --starting-position LATEST \
  --provisioned-poller-config '{
    "MinimumPollers": 1, 
    "MaximumPollers": 10, 
    "PollerGroupName": "production-app-group"
  }'
```

要将另一个 ESM 添加到同一个组（共享 EPU 容量），请使用相同的 PollerGroupName：

```
aws lambda create-event-source-mapping \
  --function-name myFunction2 \
  --event-source-arn arn:aws:kafka:us-east-1:123456789012:cluster/MyCluster/abcd1234 \
  --topics topic2 \
  --starting-position LATEST \
  --provisioned-poller-config '{
    "MinimumPollers": 1, 
    "MaximumPollers": 10, 
    "PollerGroupName": "production-app-group"
  }'
```

**注意**  
您可以更新 `PollerGroupName` 以将 ESM 移动到其他组，也可以通过传递 `PollerGroupName` 的空字符串（""）从某个组中移除 ESM：

```
# Move ESM to a different group
aws lambda update-event-source-mapping \
  --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
  --provisioned-poller-config '{
    "MinimumPollers": 1, 
    "MaximumPollers": 10, 
    "PollerGroupName": "new-group-name"
  }'

# Remove ESM from group (use dedicated resources)
aws lambda update-event-source-mapping \
  --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
  --provisioned-poller-config '{
    "MinimumPollers": 1, 
    "MaximumPollers": 10, 
    "PollerGroupName": ""
  }'
```

#### 分组策略注意事项
<a name="kafka-grouping-strategy-considerations"></a>
+ **应用程序边界**：对属于相同应用程序或服务的 ESM 进行分组，以实现更好的成本分配和管理。考虑使用 `app-name-environment` 之类的命名约定（例如 `order-processor-prod`）。
+ **流量模式**：避免将具有高吞吐量和峰值流量模式的 ESM 分组，因为这可能会导致资源争用。
+ **影响范围**：考虑一下如果共享基础设施出现故障会带来怎样的影响。同一组中的所有 ESM 都受到共享资源限制的影响。对于任务关键型工作负载，您可能要使用单独的组或专用 ESM。

#### 成本优化示例
<a name="kafka-cost-optimization-example"></a>

设想这样一个场景：您拥有 10 个 ESM，每个都配置了 1 个事件轮询器，且其吞吐量均低于 2 MB/s：

**不分组：**
+ 每个 ESM 都需要自己的 EPU
+ 所需的 EPU 总数：10
+ 每个 EPU 成本：美国东部（弗吉尼亚州北部）每小时 0.185 美元
+ 每月 EPU 成本（720 小时）：10 × 720 × 0.185 美元 = 1332 美元

**进行分组：**
+ 所有 10 个 ESM 均共享 EPU 容量
+ 1 个 EPU 中可容纳 10 个事件轮询器（每个 EPU 支持新增 10 个轮询器）
+ 所需的 EPU 总数：1
+ 每月 EPU 成本（720 小时）：1 × 720 × 0.185 美元 = 133.20 美元
+ **节省成本：90%**（每月可节省 1198.80 美元）