

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Apache Kafka クライアントのためのベストプラクティス
<a name="bestpractices-kafka-client"></a>

Apache Kafka と Amazon MSK を使用する場合、最適なパフォーマンスと信頼性を実現するためには、クライアントとサーバーの両方を最適に設定することが重要です。このガイドでは、Amazon MSK のクライアント側設定におけるベストプラクティスの推奨事項を提供します。

Amazon MSK Replicator のベストプラクティスについては、「[ベストプラクティス](msk-replicator-best-practices.md)」を参照してください。Standard および Express ブローカーのベストプラクティスについては、「[標準ブローカーと Express ブローカーのベストプラクティス](bestpractices-intro.md)」を参照してください。

**Topics**
+ [Apache Kafka クライアントの可用性](#bestpractices-kafka-client-client-availability)
+ [Apache Kafka クライアントのパフォーマンス](#bestpractices-kafka-client-performance)
+ [Kafka クライアントモニタリング](#bestpractices-kafka-client-monitoring)

## Apache Kafka クライアントの可用性
<a name="bestpractices-kafka-client-client-availability"></a>

Apache Kafka のような分散システムで、信頼性と耐障害性に優れたメッセージングインフラストラクチャを維持するためには、高可用性の確保が不可欠です。ブローカーがオフラインになるイベントには、アップグレード、パッチ適用、ハードウェア障害、ネットワークの問題など、計画的なものと計画的でないものの両方があります。Kafka クラスターには、オフラインブローカーに対する寛容性があり、このため Kafka クライアントでは、ブローカーのフェイルオーバーを円滑に処理する必要があります。Kafka クライアントの高可用性を確保するために、以下のベストプラクティスが推奨されています。

**プロデューサーの可用性**
+ ブローカーのフェイルオーバー中に失敗したメッセージの再送信をプロデューサーに指示するには、`retries` を設定します。ほとんどのユースケースでは、整数の最大値または同様の大きな値が推奨されます。これが適切でない場合、Kafka の高可用性が損なわれます。
+ `delivery.timeout.ms` を設定すると、メッセージを送信してブローカーから確認応答を受信する間の、合計時間の上限が指定されます。これには、メッセージの有効期間についての、ビジネス要件を反映する必要があります。フェイルオーバーの操作を完了するのに十分な再試行ができるように、時間制限を十分高く設定します。ほとんどのユースケースでは、60 秒以上の値にすることをお勧めします。
+ `request.timeout.ms` には、再送信を試みる前に 1 つのリクエストが待機する最大時間を設定します。ほとんどのユースケースでは、10 秒以上の値にすることをお勧めします。
+ `retry.backoff.ms` を設定すると、再試行ストームと可用性への影響を回避するように再試行間の遅延を指定できます。ほとんどのユースケースでは、最小値の 200 ミリ秒にすることをお勧めします。
+ `acks=all` では高い耐障害性を設定します。これは、ISR 内のすべてのパーティションで書き込みが確実に承認されるように、`RF=3` および `min.isr=2` のサーバー側設定と合わせる必要があります。1 つのブローカーのオフライン中、この `min.isr` は `2` に設定します。

**コンシューマーの可用性**
+ 新規または再作成されたコンシューマーグループの場合、最初に `auto.offset.reset` を `latest` に設定します。これにより、トピック全体を消費することでクラスター負荷が追加されるリスクを回避できます。
+ `enable.auto.commit` を使用する場合は `auto.commit.interval.ms` を設定します。ほとんどのユースケースでは、追加的な負荷のリスクを避けるために、最小値の 5 秒にすることをお勧めします。
+ 一時的なエラー (例えば、サーキットブレーカーや指数バックオフのあるスリープなど) を処理するために、コンシューマーのメッセージ処理コード内に例外処理を実装します。これが適切でない場合、アプリケーションがクラッシュし、過剰な再分散が発生する可能性があります。
+ トランザクションメッセージの読み取り方法を制御するには、`isolation.level` を設定します。

  デフォルトでは、常に暗黙的に `read_uncommitted` を設定することをお勧めします。これは、一部のクライアント実装には含まれていません。

  階層型ストレージを使用する場合は、`read_uncommitted` の値にすることをお勧めします。
+ 最も近いレプリカリードを使用するには、`client.rack` を設定します。ネットワークトラフィックのコストとレイテンシーを最小限に抑えるために、`az id ` を設定することをお勧めします。[「ラック認識を使用して Amazon MSK コンシューマーのネットワークトラフィックコストを削減する](https://aws.amazon.com/blogs/big-data/reduce-network-traffic-costs-of-your-amazon-msk-consumers-with-rack-awareness/)」を参照してください。

**コンシューマーの再分散**
+ `session.timeout.ms` には、実装された起動ジッターを含め、アプリケーションの起動時間より大きい値を設定します。ほとんどのユースケースでは、値を60 秒にすることをお勧めします。
+ `heartbeat.interval.ms` を設定すると、グループコーディネーターがコンシューマーを正常と見なす方法をファインチューニングできます。ほとんどのユースケースでは、値を 10 秒にすることをお勧めします。
+ コンシューマーがグループを離れるタイミングを認識するためにセッションタイムアウトに依存するのではなく、アプリケーション内でシャットダウンフックを設定し、SIGTERM 上でコンシューマーをクリーンに閉じます。Kstream アプリケーションでは、`internal.leave.group.on.close` の値に `true` を設定できます。
+ `group.instance.id` には、コンシューマーグループ内の個別の値を設定します。ホスト名、タスク ID、または ポッド ID が理想的です。トラブルシューティング中、より確定的な動作をさせ、クライアント/サーバーログの相関関係を向上させるために、この設定は常に行うことをお勧めします。
+ 平均デプロイ時間にに合った値を `group.initial.rebalance.delay.ms` に設定します。これにより、デプロイ中の継続的な再分散が停止します。
+ スティッキーアサイナーを使用するように `partition.assignment.strategy` を設定します。`StickyAssignor` または `CooperativeStickyAssignor` が推奨されます。

## Apache Kafka クライアントのパフォーマンス
<a name="bestpractices-kafka-client-performance"></a>

Kafka クライアントの高パフォーマンスを保証するためには、以下のベストプラクティスが推奨されます。

**プロデューサーのパフォーマンス**
+ バッチが満たされるまでのプロデューサーの待機時間を制御するには、`linger.ms` を設定します。バッチが小さいほど、一度に変換されるスレッドと I/O 操作が多くなるため、Kafka には計算コストがかかります。推奨される値は、次のようになります。

  低レイテンシーを含むすべてのユースケースについて、最小値は 5 ミリ秒です。

  ほとんどのユースケースでは、25 ミリ秒より大きい値にすることをお勧めします。

  低レイテンシーのユースケースで、ゼロの値を使用することはお勧めしません。 (通常、値が 0 の場合には、IO オーバーヘッドが原因でレイテンシーが発生します)。
+ クラスターに送信されるバッチサイズを制御するには、`batch.size` を設定します。これは、64KB または 128KB の値に増やすことをお勧めします。
+ より大きなバッチサイズを使用する場合には、`buffer.memory` を設定します。ほとんどのユースケースでは、値を 64MB にすることをお勧めします。
+ バイトの受信に使用される TCP バッファを制御するには `send.buffer.bytes` を設定します。レイテンシーの高いネットワークでプロデューサーを実行するときに、OS がこのバッファを管理できるようにするには、値を -1 にすることをお勧めします。
+ バッチの圧縮を制御するには、compression.type を設定します。高レイテンシーネットワークでは、lz4 または zstd のいずれかでプロデューサーを実行することをお勧めします。

**コンシューマーのパフォーマンス**
+ `fetch.min.bytes` を設定すると、有効になる最小フェッチサイズを制御して、フェッチ数とクラスター負荷を減らせます。

  すべてのユースケースで、最小値を 32 バイトにすることをお勧めします。

  ほとんどのユースケースでは、より大きな 128 バイトの値にすることをお勧めします。
+ fetch.max.wait.ms を設定すると、fetch.min.bytes が無視されるまでコンシューマーが待機する時間が決定されます。ほとんどのユースケースでは、値を 1000ms にすることをお勧めします。
+ より優れた並列性と耐障害性を実現するため、消費者の数はパーティション数以上であることを推奨します。状況によっては、低スループットトピックのパーティション数よりも少ないコンシューマーを選択することもできます。
+ バイトの受信に使用される TCP バッファを制御するには `receive.buffer.bytes` を設定します。高レイテンシーネットワークでコンシューマーを実行するときに、OS がこのバッファを管理できるようにするには、値を -1 にすることをお勧めします。

**クライアント接続**

接続ライフサイクルには、Kafka クラスターでの計算コストとメモリコストが発生します。一度に作成された接続が多すぎると負荷が発生し、Kafka クラスターの可用性に影響を与えることがあります。この可用性への影響により、アプリケーションでさらに多くの接続が作成され、それが直列的な障害を発生することにつながり、完全な停止に至ることがよくあります。多数の接続は、合理的なレートで作成した場合に実現できます。

接続作成の高いレートを管理するには、以下の緩和策をお勧めします。
+ アプリケーションデプロイメカニズムがすべてのプロデューサー/コンシューマーを一度に再起動するのではなく、可能な限り小さなバッチで再起動するようにします。
+ デベロッパーは、アプリケーションレイヤーにおいて管理者クライアント、プロデューサークライアント、またはコンシューマークライアントを作成する前に、ランダムジッター (ランダムスリープ) が実行されていることを保証してください。
+ SIGTERM で接続を閉じる際には、ランダムなスリープを実行して、すべての Kafka クライアントが同時に閉じられないようにする必要があります。ランダムスリープのタイムアウトは、SIGKILL が発生する前の範囲である必要があります。  
**Example 例 A (Java)**  

  ```
  sleepInSeconds(randomNumberBetweenOneAndX);
                          this.kafkaProducer = new KafkaProducer<>(this.props);
  ```  
**Example 例 B (Java)**  

  ```
  Runtime.getRuntime().addShutdownHook(new Thread(() -> {
      sleepInSeconds(randomNumberBetweenOneAndTwentyFive);
      kafkaProducer.close(Duration.ofSeconds(5));
  });
  ```
+ デベロッパーは、アプリケーションレイヤーにおいて、クライアントがアプリケーションごとに 1 回だけシングルトンパターンで作成されることを保証してください。例えば、lambda を使用する場合、クライアントはメソッドハンドラーではなくグローバルスコープで作成されるようにします。
+ 安定することを目標に、接続数をモニタリングすることをお勧めします。デプロイ時とブローカーフェイルオーバー中は、接続の作成/クローズ/シフトは正常です。

## Kafka クライアントモニタリング
<a name="bestpractices-kafka-client-monitoring"></a>

Kafka クライアントのモニタリングは、Kafka エコシステムの正常性と効率を維持するために不可欠です。Kafka の管理者、開発者、または運用チームメンバーのいずれであっても、計画的および計画外のイベント中のビジネスへの影響を把握するためには、クライアント側のメトリクスを有効にすることが極めて重要です。

好みのメトリクスキャプチャメカニズムを使用して、次のクライアント側メトリクスをモニタリングすることをお勧めします。

でサポートチケットを引き上げるときは AWS、インシデント中に観察された異常値を含めます。また、エラー (警告ではない) を詳述したクライアントアプリケーションログのサンプルも含めます。

**プロデューサーメトリクス**
+ byte-rate (バイトレート)
+ record-send-rate (レコード送信レート)
+ records-per-request-avg (要求あたりレコードの平均)
+ acks-latency-avg (承認遅延の平均)
+ request-latency-avg (要求遅延の平均)
+ request-latency-max (要求遅延の最大)
+ record-error-rate (レコードエラーレート)
+ record-retry-rate (レコード再試行レート)
+ error-rate (エラーレート)

**注記**  
再試行による一時的なエラーは懸念の対象ではありません。これは、リーダーのフェイルオーバーおよびネットワーク再送信などの一時的な問題を処理するための、Kafka のプロトコルの一部分です。`record-send-rate` で、プロデューサーが再試行を続行しているかどうかを確認できます。

**コンシューマーメトリクス**
+ records-consumed-rate (レコード使用レート)
+ bytes-consumed-rate (バイト使用レート)
+ fetch-rate (フェッチレート)
+ records-lag-max (レコードの最大時間差)
+ record-error-rate (レコードエラーレート)
+ fetch-error-rate (フェッチエラーレート)
+ poll-rate (ポーリングレート)
+ rebalance-latency-avg (リバランス遅延の平均)
+ commit-rate (コミットレート)

**注記**  
高いフェッチ率とコミット率は、クラスターに不要な負荷をもたらします。リクエストの処理には大きなバッチが適しています。

**一般的なメトリクス**
+ connection-close-rate (接続解除レート)
+ connection-creation-rate (接続作成レート)
+ connection-count (接続数)

**注記**  
接続の頻作成/切断回数が多いと、クラスターに不要な負荷の原因になります。