次のセットアップのパフォーマンスを確認するために、一連の負荷テストを実行しています。
Node.js test suite (client) --> StatsD (server) --> Graphite (server)
つまり、node.jsテストスイートは、x秒ごとに一定量のメトリックを別のサーバーにあるStatsDインスタンスに送信します。次にStatsDは、同じサーバーにあるGraphiteインスタンスに毎秒メトリックをフラッシュします。次に、テストスイートによって実際に送信されたメトリックの数と、グラファイトによって受信されたメトリックの数を調べて、テストスイートとグラファイトの間のパケット損失を判断します。
ただし、20〜50%の範囲の非常に大きなパケットドロップ率(UDPプロトコルで送信されていることに注意してください)が発生する場合があることに気付きました。それで、これらのパケットがドロップされている場所を調べ始めたのは、StatsDのパフォーマンスの問題の可能性があるためです。そこで、システムのすべての部分でメトリックのロギングを開始し、このドロップが発生した場所を追跡しました。そして、これは物事が奇妙になる場所です。
tcpdump を使用して、テストの実行後に検査するキャプチャファイルを作成しています。しかし、tcpdumpを実行してテストを実行すると、パケット損失はほとんどありません。 tcpdumpがどういうわけか私のテストのパフォーマンスを向上させているようで、なぜ、どのようにこれを行うのか理解できません。次のコマンドを実行して、サーバーとクライアントの両方でtcpdumpメッセージをログに記録しています。
tcpdump -i any -n port 8125 -w test.cap
1つの特定のテストケースでは、40000メトリック/秒を送信しています。 tcpdumpの実行中のテストのパケット損失は約4%ですが、テストのないテストのパケット損失は約20%です。
どちらのシステムも、次の設定でXen VMとして実行されています。
潜在的な原因についてすでに確認したこと:
Tcpdumpの実行中は、着信フレームの読み取り時にかなりプロンプトが表示されます。私の仮説は、NICのパケットリングバッファー設定が小さいサイズのビットかもしれないというものです。 tcpdumpの実行中は、よりタイムリーに空になります。
Red Hatサブスクライバーの場合、このサポート記事は非常に役立ちます パケット受信の概要 。そこにはまだあなたが考慮していないと思うことがいくつかあります。
システムがIRQを処理する方法を検討してください。ネットワークインターフェイスの 'dev_weight'を増やすことを検討してください(NICからユーザースペースに読み取られるパケットが増えることを意味します);アプリケーションがソケットを読み取る頻度を確認します(専用スレッドを使用できるか、スケーラビリティに関する既知の問題/回避策があります)。
NICフレームバッファを増やします(ethtool
コマンドを使用して---set-ring
などの引数)。
「受信側のスケーリング」を見て、少なくともその数の受信スレッドを使用してトラフィックを読み取ります。
Tcpdumpは パケットリングバッファ のカーネルサポートを使用するなど、何かクールなことをしているのでしょうか。それはあなたが見ている行動を説明するのに役立ちます。
どのパワーガバナーを使用していますか? 「オンデマンド」または「保守的な」ガバナーでも同様の動作が見られます。
「パフォーマンス」ガバナーを使用して、サーバーBIOSの省電力機能を無効にしてみてください。
それは何かを変えますか?
受信側はパケットレートを処理できないだけだと思います。その理由は次のとおりです。
クライアント上でtcpdumpを使用するとドロップされるパケットが減少します。tcpdumpはクライアントの速度を低下させているため、サーバーではパッカーレートがはるかに低く、それでも部分的に扱う。クライアントとサーバーの両方でRX/TXパケットカウンターをチェックして、この仮説を確認できるはずです。
uDPバッファーの受信/送信サイズを増やしたとおっしゃっていましたが、詳細を教えていただけますか?サーバーでrmem_maxとrmem_defaultの両方を変更することが重要です。例:sysctl -w net.core.rmem_max=524287 sysctl -w net.core.wmem_max=524287 sysctl -w net.core.rmem_default=524287 sysctl -w net.core.wmem_default=524287
Statsdとノードアプリケーションを停止し、システムがアイドル状態のときに iperf を使用して、ネットワーク/カーネルが処理できるパケットレートをテストします。 iperfで40Kパケット/秒をストリーミングできても、statsdではストリーミングできない場合は、statsdのチューニングに集中する必要があります。
また、net.core.netdev_max_backlogを調整することを忘れないでください。特定のインターフェイスがカーネルが処理できるよりも速くパケットを受信したときに、キューに入れられる最大パケット数。
もう1つの方法はip_conntarck
モジュールです。linux-boxが新しい接続を受け入れてもよろしいですか?テスト:
root@debian:/home/mohsen# sysctl net.ipv4.netfilter.ip_conntrack_max
net.ipv4.netfilter.ip_conntrack_max = 65536
root@debian:/home/mohsen# sysctl net.ipv4.netfilter.ip_conntrack_count
net.ipv4.netfilter.ip_conntrack_count = 29
テストする必要があります
net.ipv4.netfilter.ip_conntrack_max > net.ipv4.netfilter.ip_conntrack_count
max == countの場合、最大接続はフルであり、linux-boxは新しい接続を受け入れることができません。
ip_conntrackがない場合は、modprobe ip_conntrack
から簡単にロードできます