大量のメトリクスの送信

DogStatsD には、アプリケーションから生成されるメトリクスを、転送プロトコルを介して Agent に送信するという機能があります。このプロトコルには UDP (User Datagram Protocol) または UDS (Unix Domain Socket) が使用されます。

DogStatsD を使用して大量のメトリクスを 1 つの Agent に送信する際、適切な措置を講じずに実行すると以下のような問題が発生する場合があります。

  • Agent の CPU 使用量の増加
  • データグラムやメトリクスのドロップ
  • DogStatsD クライアントライブラリ (UDS) により返されるエラー

これらの問題の大半は、以下で説明するようにコンフィギュレーションを調整することで軽減できます。

一般的な方法

Datadog 公式クライアントを使用する

DataDog は、すべての主要なプログラミング言語について、公式 DogStatsD クライアントの最新バージョンを使用することをお勧めします。

クライアント側のバッファリングを有効にする

StatsD や DogStatsD のクライアントが、デフォルトで 1 つのデータグラムごとに 1 つのメトリクスを送信する場合がありますが、これによりクライアントやオペレーティングシステム、そして Agent のオーバーヘッドは非常に高くなります。複数のメトリクスを 1 つのダイアグラムにバッファリングできるようにクライアントを作成し、このオプションを有効にすることで問題を著しく改善できます。

バッファリングをサポートする、コミュニティサポートの DogStatsD クライアントを使用している場合、Agent 側のデータごとのバッファサイズ (デフォルトで 8KB、dogstatsd_buffer_size を使用して Agent で構成可能) およびネットワーク/OS の最大データグラムサイズを超えない最大データグラムサイズを構成するようにしてください。

DogStatsD が公式にサポートするクライアントの例をご紹介します。

以下の例では、Datadog の公式 Ruby ライブラリ [dogstatsd-ruby][1] を使用して、フラッシュがトリガーされたときに 1 つのパケットでメトリクスを送信するバッファー付き DogStatsD クライアントインスタンスを作成します。

require 'datadog/statsd'

statsd = Datadog::Statsd.new('127.0.0.1', 8125)

statsd.increment('example_metric.increment', tags: ['environment:dev'])
statsd.gauge('example_metric.gauge', 123, tags: ['environment:dev'])

# synchronous flush
statsd.flush(sync: true)

メトリクスのサンプリング

クライアント側でサンプリングレートの値を設定すると、DogStatsD クライアントから Agent へのトラフィックを減らすことができます。たとえば、サンプリングレートを 0.5 にすると、送信される UDP パケットの数が半減します。この方法には、トラフィックが減る代わりに精度や粒度がやや低下するという欠点もあります。

詳しい情報やコードの例が必要な場合は、DogStatsD の「サンプリングレート」パラメータの説明を参照してください。

UDS (Unix Domain Socket) を介した DogStatsD の使用

UDS は DogStatsD ペイロードの転送に使用される、プロセス間通信プロトコルです。UDP と比べてオーバーヘッドが小さく、多くのシステムで DogStatsD のフットプリントを減らすことができます。

クライアント側の集計

クライアントライブラリは、クライアント側でメトリクスを集計し、Datadog Agent に送信しなければならないメッセージの数を減らし、IO パフォーマンスとスループットを向上させることができます。

クライアント側の集計は、v5.0.0 以降の Go クライアントでのみ利用可能です。

詳しくは、クライアント側の集計を参照してください。

複数のメトリクス処理パイプラインを実行し、パケットドロップを制限する

DogStatsD サーバーが UDS を使用しており、高いスループットでパケットをドロップしている場合、CPU をより多く使用するように構成することで処理速度を改善し、パケットドロップを減少させることができる場合があります。

また、クライアントテレメトリーがパケットドロップを示し、サーバーが 2 CPU または 2 コア以上使用可能であっても使用しない場合は、DogStatsD サーバーを構成することができます。

パケットドロップを減らすには

  1. クライアントキューのサイズを 8192 に増やします。詳細については、クライアントライブラリの構成を参照してください。ドロップの量が減少し、アプリケーションがより多くの RAM を使用するようになるかもしれません。
  2. さらに、Datadog Agent の構成で、dogstatsd_pipeline_autoadjust: true 機能を有効にすることができます。Agent はカスタムメトリクスの処理に複数のコアを使用するため、CPU 使用率が高くなることがありますが、パケットドロップは少なくなります。

オペレーティングシステムのカーネルバッファ

ほとんどのオペレーティングシステムは、メトリクスを含むデータグラムを UDP や UDS を介して受信し、バッファに追加します。バッファにはサイズ制限があるため、その最大値に達すると、データグラムとその中に含まれるメトリクスがドロップを始めます。この最大値を調整すれば、受信したメトリクスを Agent が処理する時間を増やすことができます。

UDP (User Datagram Protocol) の場合

Linux

ほとんどの Linux ディストリビューションで、カーネル バッファの最大サイズはデフォルトで 212992(208 KB) に設定されています。これを確認するには、次のコマンドを使用します。

$ sysctl net.core.rmem_max
net.core.rmem_max = 212992

DogStatsD ソケットバッファの最大サイズを 25MB に設定するには、次を実行します。

sysctl -w net.core.rmem_max=26214400

これを永続的に変更するには、次のコンフィギュレーションを /etc/sysctl.conf に追加します。

net.core.rmem_max = 26214400

続いて、Agent の dogstatsd_so_rcvbuf コンフィギュレーションオプションを、datadog.yaml 内で同じ数値に設定します。

dogstatsd_so_rcvbuf: 26214400

Kubernetes で Agent または DogStatsD を開発している場合は、Kubernetes の sysctl に関するメモ セクションを参照してください。

UDS (Unix Domain Socket) 経由

Linux

UDS ソケットの場合、リーダーがライターより遅い場合、Linux はキュー内のデータグラムを内部的にバッファリングしています。このキューのサイズは、Linux がソケットごとにバッファリングするデータグラムの最大数を表します。この値は、次のコマンドで照会できます。

sysctl net.unix.max_dgram_qlen

値が 512 未満の場合は、次のコマンドを使用して 512 以上に増やすことができます。

sysctl -w net.unix.max_dgram_qlen=512

これを永続的に変更するには、次のコンフィギュレーションを /etc/sysctl.conf に追加します。

net.unix.max_dgram_qlen = 512

同様に、net.core.wmem_max を 4MiB に増やして、クライアントの書き込みパフォーマンスを向上させることができます。

net.core.wmem_max = 4194304

続いて、Agent の dogstatsd_so_rcvbuf コンフィギュレーションオプションを、datadog.yaml 内で同じ数値に設定します。

dogstatsd_so_rcvbuf: 4194304

Kubernetes の sysctl に関するメモ

Kubernetes を使用して Agent や DogStatsD をデプロイしていて、上記のように sysctl を構成する場合は、コンテナごとに値を設定します。net.* sysctl にネームスペースが設定されている場合は、ポッドごとに設定できます。Kubernetes クラスターでの sysctl の使用に関する Kubernetes のドキュメントを参照してください。

適切なパケットサイズを確保する

適切なサイズのパケットを Datadog Agent の DogStatsD サーバーに送信することにより、余分な CPU 使用を回避します。公式 DogStatsD クライアントの最新バージョンは、パフォーマンスに最適化されたサイズのパケットを送信します。

最新の Datadog DogStatsD クライアントのいずれかを使用している場合は、このセクションをスキップできます。

送信されたパケットが小さすぎる場合、Datadog Agent は複数を一緒にパックして、後でパイプラインでバッチ処理します。公式 DogStatsD クライアントは、メトリクスをグループ化して、パケットあたりのメトリクスの数の比率を最適化できます。

DogStatsD クライアントが dogstatsd_buffer_size のサイズのパケットを送信する場合、Datadog Agent が最も最適に動作します。パケットはバッファサイズより大きくしてはなりません。そうでない場合、Agent はパケットをバッファに完全にロードできず、メトリクスが不正になります。DogStatsD クライアントの対応するコンフィギュレーションフィールドを使用します。

UDP に関する注意: UDP パケットは通常 Ethernet および IP レイヤーを通過するため、パケットサイズをネットワーク上の単一の Ethernet フレームよりも小さい値に制限することにより、IP パケットの断片化を回避できます。ほとんどの場合、IPv4 ネットワークは 1500 バイトの MTU で構成されているため、この状況では送信パケットのパケットサイズを 1472 に制限する必要があります。
UDS に関する注意: 最高のパフォーマンスを得るには、UDS パケットサイズを 8192 バイトにする必要があります。

Agent の最大メモリ使用量を制限する

Agent は、DogStatsD クライアントから送信されたメトリクスのバーストを吸収しようとしますが、そのためには、メモリを使用する必要があります。これが短時間であり、このメモリが OS にすぐに解放された場合でも、スパイクが発生し、メモリ使用量の制限によりポッドまたはコンテナがエビクションされる可能性があるコンテナ化された環境で問題になる可能性があります。

アプリケーションでバーストでメトリクスを送信することは避けてください。これにより、Datadog Agent が最大メモリ使用量に達するのを防ぎます。

最大メモリ使用量を制限するために注意すべきもう 1 つのことは、バッファリングを減らすことです。Agent 内の DogStatsD サーバーのメインバッファは、dogstatsd_queue_size フィールドで構成できます (Datadog Agent 6.1.0 以降)。そのデフォルト値の 1024 は、およその最大メモリ使用量である 768MB を引き起こします。

: バッファサイズを小さくすると、パケットドロップの数が増える可能性があります。

この例では、DogStatsD の最大メモリ使用量を約 384MB に減らします。

dogstatsd_queue_size: 512

バースト検知を使用してアプリケーションからメトリクスのバーストを検知するには、次のセクションを参照してください。

メトリクスの処理統計とバースト検知を有効にする

DogStatsD には、どのメトリクスが最も多く処理されたかを把握するのに役立つ統計モードが搭載されています。

: メトリクス統計モードを有効にすると、DogStatsD のパフォーマンスが低下する可能性があります。

この統計モードは以下のいずれかの方法で有効化できます。

  • コンフィギュレーションファイルで dogstatsd_stats_enabletrue に設定
  • 環境変数 DD_DOGSTATSD_STATS_ENABLEtrue に設定
  • datadog-agent config set dogstatsd_stats true コマンドを使用して、ランタイム時に有効化を行います。ランタイム時にこれを無効化するには、datadog-agent config set dogstatsd_stats false コマンドを使用してください。

このモードを有効化したら、コマンド datadog-agent dogstatsd-stats を実行します。処理されたメトリクスのリストが受信したメトリクスの降順で返されます。

このモードでシステムを実行すると、DogStatsD サーバーがバースト検知メカニズムを実行します。バーストが検知されたら警告ログが送信されます。例:

DogStatSd によりメトリクスのバーストが検知されました。最後の 5 秒間のメトリクスカウントは次の通りです: [250 230 93899 233 218]

クライアント側のテレメトリー

DogStatsD クライアントは、デフォルトでテレメトリーメトリクスを Agent に送信します。これを利用して、ボトルネックが存在する場合にトラブルシューティングを行うことができます。各メトリクスには、クライアントの言語とバージョンがタグ付けされます。これらのメトリクスはカスタムメトリクスとしてカウントされません。

以下のタグは、すべてのクライアントに共通してタグ付けされます。

タグ説明
clientクライアントの言語client:py
client_versionクライアントのバージョンclient_version:1.2.3
client_transportクライアントが使用する転送プロトコル (udp または uds)client_transport:uds

: UDP を使用すると、クライアントがネットワークエラーを検出できないため、バイトやパケットがドロップしてもメトリクスには反映されません。

バージョン 4.6.0 以降の Ruby クライアントが必要です。

datadog.dogstatsd.client.metrics
メトリクスタイプ: カウント
アプリケーションによって DogStatsD クライアントに送信された metrics の数 (サンプリング前)。
datadog.dogstatsd.client.events
メトリクスタイプ: カウント
アプリケーションによって DogStatsD クライアントに送信された events の数。
datadog.dogstatsd.client.service_checks
メトリクスタイプ: カウント
アプリケーションによって DogStatsD クライアントに送信された service_checks の数。
datadog.dogstatsd.client.bytes_sent
メトリクスタイプ: カウント
Agent に正常に送信されたバイト数。
datadog.dogstatsd.client.bytes_dropped
メトリクスタイプ: カウント
DogStatsD クライアントによってドロップされたバイト数。
datadog.dogstatsd.client.packets_sent
メトリクスタイプ: カウント
Agent に正常に送信されたデータグラムの数。
datadog.dogstatsd.client.packets_dropped
メトリクスタイプ: カウント
DogStatsD クライアントによってドロップされたデータグラムの数。

テレメトリーを無効にするには、 disable_telemetry パラメーターを true に設定します。

Datadog::Statsd.new('localhost', 8125, disable_telemetry: true)

クライアントコンフィギュレーションについて詳しくは、DataDog/dogstatsd-ruby を参照してください。

その他の参考資料

PREVIEWING: brett.blue/reorg-otel