

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 标准代理的最佳实践
<a name="bestpractices"></a>

本主题概述使用 Amazon MSK 时应遵循的一些最佳实践。有关 Amazon MSK 复制器最佳实践的信息，请参阅[使用 MSK 复制器的最佳实践](msk-replicator-best-practices.md)。

## 客户端注意事项
<a name="bestpractices-client-side-considerations"></a>

应用程序的可用性和性能不仅取决于服务器端设置，还取决于客户端的设置。
+ 为您的客户端配置高可用性 在 Apache Kafka 这样的分布式系统中，确保高可用性对于维护可靠且容错的消息传递基础设施至关重要。代理将因计划内和计划外事件（例如升级、修补、硬件故障和网络问题）而离线。Kafka 集群可以容忍代理离线，因此 Kafka 客户端也必须妥善处理代理失效转移。有关全部详细信息，请参阅[Apache Kafka 客户端的最佳实践](bestpractices-kafka-client.md)。
+ 确保客户端连接字符串至少包含来自每个可用区的一个代理。在客户端的连接字符串中具有多个代理，则可在特定代理脱机进行更新时实现失效转移。有关如何获取具有多个代理的连接字符串的信息，请参阅[获取 Amazon MSK 集群的引导代理](msk-get-bootstrap-brokers.md)。
+ 运行性能测试，验证客户端配置是否能使您实现性能目标。

## 服务器端注意事项
<a name="standard-server-side-considerations"></a>

### 调整集群的大小：每个标准代理的分区数量
<a name="partitions-per-broker"></a>

下表显示了建议的每个标准代理的分区数量（包括领导副本和跟随者副本）。建议分区数量不是强制执行的，对于跨预置主题分区发送流量的场景，这是最佳的做法。


| 经纪人规模 | 建议的每个代理的分区数量（包括领导副本和跟随者副本）。 | 支持更新操作的最大分区数 | 
| --- | --- | --- | 
| kafka.t3.small | 300 | 300 | 
| kafka.m5.large 或 kafka.m5.xlarge | 1000 | 1500 | 
| kafka.m5.2xlarge | 2000 | 3000 | 
| kafka.m5.4xlarge、kafka.m5.8xlarge、kafka.m5.12xlarge、kafka.m5.16xlarge 或 kafka.m5.24xlarge | 4000 | 6000 | 
| kafka.m7g.large 或 kafka.m7g.xlarge | 1000 | 1500 | 
| kafka.m7g.2xlarge | 2000 | 3000 | 
| kafka.m7g.4xlarge、kafka.m7g.8xlarge、kafka.m7g.12xlarge 或 kafka.m7g.16xlarge | 4000 | 6000 | 

如果遇到高分区、低吞吐量的用例，即分区数较高，但各分区之间没有发送流量，则每个代理可以打包多个分区，前提是您已进行了充分的测试和性能测试，证实集群在较高分区数下仍保持正常。如果每个代理的分区数量超过允许的最大值，并且您的集群过载，将会阻止您执行以下操作：
+ 更新集群配置
+ 将集群更新为较小的代理大小
+ 将 AWS Secrets Manager 密钥与具有 SASL/SCRAM 身份验证的集群相关联

大量分区还可能导致 Prometheus 抓取 CloudWatch 和抓取时缺少 Kafka 指标。

有关选择分区数的指导，请参阅 [Apache Kafka 支持每个集群 20 万个分区](https://blogs.apache.org/kafka/entry/apache-kafka-supports-more-partitions)。我们还建议您执行自己的测试，以确定适合您代理的大小。有关不同代理大小的更多信息，请参阅[Amazon MSK 代理类型](broker-instance-types.md)。

### 调整集群的大小：每个集群的标准代理数量
<a name="brokers-per-cluster"></a>

要确定预置 MSK 集群的适当标准代理数量并了解成本，请参阅 [MSK Sizing and Pricing](https://view.officeapps.live.com/op/view.aspx?src=https%3A%2F%2Fdy7oqpxkwhskb.cloudfront.net%2FMSK_Sizing_Pricing.xlsx&wdOrigin=BROWSELINK) 电子表格。此电子表格提供了与类似的、自我管理的基于 EC2 的 Apache Kafka 集群相比，估计的预置 MSK 集群大小和相关 Amazon MSK 成本。有关电子表格中的输入参数的更多信息，请将鼠标指针悬停在参数描述的上方。此表提供的是保守估计值，为新的预置 MSK 集群提供了一个起点。集群的性能、大小和成本取决于您的用例，建议您通过实际测试进行验证。

要了解底层基础架构如何影响 Apache Kafka 性能，请参阅大数据博客中的[调整您的 Apache Kafka 集群规模以优化性能和成本的最佳实践](https://aws.amazon.com/blogs/big-data/best-practices-for-right-sizing-your-apache-kafka-clusters-to-optimize-performance-and-cost/)。 AWS 这篇博客文章提供了有关如何调整集群大小以满足吞吐量、可用性和延迟要求的信息。它还提供了诸如何时应**纵向扩展，何时应横向**扩展等问题的答案，以及有关如何持续验证生产集群大小的指导。有关基于分层存储的集群的信息，请参阅[使用 Amazon MSK 分层存储运行生产工作负载的最佳实践](https://aws.amazon.com/blogs/big-data/best-practices-for-running-production-workloads-using-amazon-msk-tiered-storage/)。

### 优化 m5.4xl、m7g.4xl 或更大实例的集群吞吐量
<a name="optimize-broker-threads"></a>

使用 m5.4xl、m7g.4xl 或更大实例时，您可以通过调整 num.io.threads 和 num.network.threads 配置来优化预置 MSK 集群的吞吐量。

Num.io.threads 是标准代理用于处理请求的线程数。添加更多线程（不超过实例大小支持的 CPU 核心数量）有助于提高集群的吞吐量。

Num.network.threads 是标准代理用于接收所有传入请求和返回响应的线程数。网络线程将传入请求放在请求队列中，以供 io.threads 处理。将 num.network.threads 设置为实例大小支持的 CPU 核心数量的一半，即可充分使用新的实例大小。

**重要**  
如果不先增加 num.io.threads，请勿增加 num.network.threads，因为这可能会导致与队列饱和相关的拥塞。

下表描述了每个实例大小的建议设置。


| 实例大小 | num.io.threads 的推荐值 | num.network.threads 的推荐值 | 
| --- | --- | --- | 
|  m5.4xl  |  16  |  8  | 
|  m5.8xl  |  32  |  16  | 
|  m5.12xl  |  48  |  24  | 
|  m5.16xl  |  64  |  32  | 
|  m5.24xl  |  96  |  48  | 
|  m7g.4xlarge  |  16  |  8  | 
|  m7g.8xlarge  |  32  |  16  | 
|  m7g.12xlarge  |  48  |  24  | 
|  m7g.16xlarge  |  64  |  32  | 

### 使用最新的 Kafka AdminClient 来避免主题 ID 不匹配问题
<a name="topic-id-mismatch"></a>

当您使用低于 2.8.0 的 Kafka 版本和标志`--zookeeper`，为使用 Kafka AdminClient 版本 2.8.0 或更高版本的 MSK 预配置集群增加或重新分配主题分区时，主题的 ID 会丢失（错误：与分区的主题 ID 不匹配）。请注意，`--zookeeper` 标志在 Kafka 2.5 中已弃用，并从 Kafka 3.0 开始删除。请参阅 [Upgrading to 2.5.0 from any version 0.8.x through 2.4.x](https://kafka.apache.org/documentation.html#upgrade_2_5_0)。

为防止主题 ID 不匹配，请使用 Kafka 客户端版本 2.8.0 或更高版本进行 Kafka 管理员操作。或者，2.5 及更高版本的客户端可以使用 `--bootstrap-servers` 标志代替 `--zookeeper` 标志。

### 构建高度可用的集群
<a name="ensure-high-availability"></a>

使用以下建议，以便在更新期间（例如更新代理大小或 Apache Kafka 版本时）或 Amazon MSK 更换代理时，保持预置 MSK 集群的高可用性。
+ 设置三可用区集群。
+ 确保复制因子（RF）至少为 3。请注意，在滚动更新期间，RF 为 1 可能会导致分区离线；而 RF 为 2 可能会导致数据丢失。
+ 将最小同步副本数 (minISR) 设置为最多 RF - 1。minISR 等于 RF 可能会阻止在滚动更新期间生成到集群。当一个副本处于脱机状态时，minISR 为 2 使三向复制主题可用。

### 监控 CPU 使用率
<a name="bestpractices-monitor-cpu"></a>

Amazon MSK 强烈建议您将代理的 CPU 使用率（定义为 `CPU User + CPU System`）保持在 60% 以下。这可以确保集群保留足够的 CPU 余量来处理操作事件，例如代理故障、修补和滚动升级。

Apache Kafka 可以根据需要在集群中的代理之间重新分配 CPU 负载。例如，当 Amazon MSK 检测到代理故障并从中恢复时，会执行自动维护，比如进行修补。类似地，当用户请求更改代理大小或升级版本时，Amazon MSK 会启动滚动工作流程，一次让一个代理离线。当具有领导分区的代理离线时，Apache Kafka 会重新分配分区领导权，以将工作重新分配给集群中的其他代理。通过遵循此最佳实践，您可以确保有足够的 CPU 余量来容忍此类操作事件。

**注意**  
在监控 CPU 利用率时，请注意 CPU 总使用量不仅包括 `CPU User` 和 `CPU System`。`iowait`、`irq`、`softirq` 和 `steal` 等其他类别对整体 CPU 活动也有贡献。因此，CPU 空闲*并不总是等于* `100% - CPU User - CPU System`。

您可以使用 [Amazon CloudWatch 指标数学](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/using-metric-math.html)来创建复合指标 (`CPU User + CPU System`)，并将警报设置为在平均使用量超过 60% 时触发。触发时，可考虑使用以下选项之一扩展集群：
+ 选项 1（推荐）：[将您的代理大小更新](https://docs.aws.amazon.com//msk/latest/developerguide/msk-update-broker-type.html)为下一个较大的大小。例如，如果当前大小为 `kafka.m5.large`，则更新集群以使用 `kafka.m5.xlarge`。请记住，当您更新集群中的代理大小时，Amazon MSK 会以滚动方式使代理离线，并暂时将分区领导权重新分配给其他代理。每个代理的规模更新通常需要 10-15 分钟。
+ 选项 2：如果主题中的所有消息都是从使用轮询写入的生成器那里摄取的（换句话说，消息没有密钥，顺序对使用器来说并不重要），请通过添加代理来[扩展集群](https://docs.aws.amazon.com//msk/latest/developerguide/msk-update-broker-count.html)。还要向吞吐量最高的现有主题添加分区。接下来，使用 `kafka-topics.sh --describe` 来确保将新添加的分区分配给新代理。与前一个选项相比，此选项的主要优点是您可以更精细地管理资源和成本。此外，如果 CPU 负载明显超过 60%，则可使用此选项，因为这种形式的扩展通常不会导致现有代理的负载增加。
+ 选项 3：通过添加代理来扩展预置 MSK 集群，然后使用名为 `kafka-reassign-partitions.sh` 的分区重新分配工具来重新分配现有分区。但是，如果您使用此选项，则在重新分配分区后，集群将需要花费资源将数据从一个代理复制到另一个代理。与前两个选项相比，这可能会在一开始显著增加集群的负载。因此，Amazon MSK 不建议在 CPU 利用率高于 70% 时使用此选项，因为复制会导致额外的 CPU 负载和网络流量。仅当前两个选项不可行时，Amazon MSK 才建议使用此选项。

其他建议：
+ 作为负载分配的代理，监控每个代理的 CPU 总利用率。如果代理的 CPU 利用率一直不均衡，则可能表明集群内的负载分布不均。我们建议使用 [Cruise Control](https://docs.aws.amazon.com//msk/latest/developerguide/cruise-control.html)，通过分区分配持续管理负载分配。
+ 监控生成和使用延迟。生成和使用延迟会随着 CPU 利用率呈线性增加。
+ **JMX 抓取间隔**：如果您使用 [Prometheus 功能](https://docs.aws.amazon.com/msk/latest/developerguide/open-monitoring.html)启用开源监控系统，则建议您为 Prometheus 主机配置 (prometheus.yml) 使用 60 秒或更长的抓取间隔 (scrape\$1interval: 60s)。降低抓取间隔可能会导致集群上的 CPU 使用率过高。

### 监控磁盘空间
<a name="bestpractices-monitor-disk-space"></a>

为避免存储消息的磁盘空间不足，请创建一个`KafkaDataLogsDiskUsed`监控指标的 CloudWatch 警报。当此指标的值达到或超过 85% 时，请执行下列一项或多项操作：
+ 使用 [Amazon MSK 集群的自动扩缩](msk-autoexpand.md)。您也可以手动增加代理存储空间，如 [标准代理的手动扩缩](manually-expand-storage.md) 中所述。
+ 缩短消息保留期或减小日志大小。有关如何做到这一点的信息，请参阅[调整数据保留参数](#bestpractices-retention-period)。
+ 删除未使用的主题。

有关如何设置和使用警报的信息，请参阅[使用 Amazon CloudWatch 警报](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html)。有关 Amazon MSK 指标的完整列表，请参阅[监控预置 Amazon MSK 集群](monitoring.md)。

### 调整数据保留参数
<a name="bestpractices-retention-period"></a>

使用消息不会将其从日志中删除。要定期释放磁盘空间，您可以明确指定一个保留时间段，即消息在日志中保留的时间。您也可以指定保留日志大小。当达到保留时间段或保留日志大小时，Apache Kafka 会开始从日志中删除非活动段。

要在集群级别指定保留策略，请设置以下一个或多个参数：`log.retention.hours`、`log.retention.minutes`、`log.retention.ms` 或 `log.retention.bytes`。有关更多信息，请参阅 [自定义 Amazon MSK 配置](msk-configuration-properties.md)。

您也可以在主题级别指定保留参数：
+ 要为每个主题指定一个保留时间段，请使用以下命令。

  ```
  kafka-configs.sh --bootstrap-server $bs --alter --entity-type topics --entity-name TopicName --add-config retention.ms=DesiredRetentionTimePeriod
  ```
+ 要为每个主题指定一个保留日志大小，请使用以下命令。

  ```
  kafka-configs.sh --bootstrap-server $bs --alter --entity-type topics --entity-name TopicName --add-config retention.bytes=DesiredRetentionLogSize
  ```

您在主题级别指定的保留参数优先于集群级别参数。

### 在不正常关闭后加快日志恢复
<a name="bestpractices-log-recovery-thread"></a>

在不正常关闭后，代理可能需要一段时间才能重新启动，因为它需进行日志恢复。默认情况下，Kafka 仅对每个日志目录使用一个线程来执行此恢复。例如，如果您有成千上万个分区，则日志恢复可能需要数个小时才能完成。为加快日志恢复，建议使用配置属性 [https://docs.aws.amazon.com/msk/latest/developerguide/msk-configuration-properties.html](https://docs.aws.amazon.com/msk/latest/developerguide/msk-configuration-properties.html) 增加线程数量。您可以将它设置为 CPU 核心的数量。

### 监控 Apache Kafka 内存
<a name="bestpractices-monitor-memory"></a>

建议您监控 Apache Kafka 使用的内存。否则，集群可能会变得不可用。

要确定 Apache Kafka 使用了多少内存，您可以监控 `HeapMemoryAfterGC` 指标。`HeapMemoryAfterGC` 是垃圾回收后使用的总堆内存百分比。我们建议您创建一个 CloudWatch 警报，当`HeapMemoryAfterGC`增幅超过 60% 时会采取行动。

可用于减少内存使用的步骤会有所不同，具体取决于您配置 Apache Kafka 的方式。例如，如果您使用事务性消息传递，则可以将 Apache Kafka 配置中的 `transactional.id.expiration.ms` 值从 `604800000` 毫秒减少到 `86400000` 毫秒（从 7 天减少到 1 天）。这减少了每个事务的内存占用。

### 请勿添加非 MSK 代理
<a name="bestpractices-non-msk-brokers"></a>

对于 ZooKeeper基于 MSK 预配置的集群，如果您使用 Apache ZooKeeper 命令添加代理，则这些代理不会被添加到您的 MSK 预配置集群中，并且您的 Apache ZooKeeper 将包含有关该集群的不正确信息。这可能会导致丢失数据。有关支持的预置 MSK 集群操作，请参阅[Amazon MSK 的关键功能和概念](operations.md)。

### 启用传输中加密
<a name="bestpractices-enable-in-transit-encryption"></a>

有关传输中加密以及如何启用此加密的信息，请参阅[Amazon MSK 传输中加密](msk-encryption.md#msk-encryption-in-transit)。

### 重新分配分区
<a name="bestpractices-balance-cluster"></a>

要将分区移动到同一预置 MSK 集群上的不同代理，您可以使用名为 `kafka-reassign-partitions.sh` 的分区重新分配工具。为了安全操作，建议一次调用 `kafka-reassign-partitions` 时重新分配的分区数不要超过 10 个。例如，在添加新代理以扩展集群或移动分区以移除代理之后，您可以通过将分区重新分配给新代理来重新平衡该集群。有关如何向预置 MSK 集群添加代理的信息，请参阅[扩展 Amazon MSK 集群中的代理数量](msk-update-broker-count.md)。有关如何从预置 MSK 集群中移除代理的信息，请参阅[从 Amazon MSK 集群中移除代理](msk-remove-broker.md)。有关分区重新分配工具的信息，请参阅 Apache Kafka 文档中的[扩展集群](https://kafka.apache.org/documentation/#basic_ops_cluster_expansion)。