
次の設定のパフォーマンスを判断するために、一連の負荷テストを実行しています。
Node.js test suite (client) --> StatsD (server) --> Graphite (server)
つまり、node.js テスト スイートは、別のサーバーにある StatsD インスタンスに、x 秒ごとに一定量のメトリックを送信します。次に、StatsD は同じサーバーにある Graphite インスタンスにメトリックを毎秒フラッシュします。次に、テスト スイートによって実際に送信されたメトリックの数と Graphite によって受信されたメトリックの数を調べて、テスト スイートと Graphite 間のパケット損失を判断します。
しかし、パケットドロップ率が非常に高くなることが時々あることに気付きました (UDP プロトコルで送信されていることに注意してください)。その範囲は 20 ~ 50% です。そこで、StatsD のパフォーマンスの問題である可能性があると考え、これらのパケットがドロップされている場所を調べ始めました。そこで、システムのあらゆる部分でメトリックを記録し、ドロップが発生した場所を追跡し始めました。そして、ここから奇妙なことが起こります。
私は使用していますtcpダンプテストの実行が完了した後に検査するキャプチャ ファイルを作成します。しかし、tcpdump を実行してテストを実行すると、パケット損失はほとんど発生しません。tcpdump が何らかの形でテストのパフォーマンスを向上させているように見えますが、その理由と仕組みがわかりません。次のコマンドを実行して、サーバーとクライアントの両方で tcpdump メッセージをログに記録しています。
tcpdump -i any -n port 8125 -w test.cap
ある特定のテストケースでは、40000メトリック/秒を送信しています。tcpdumpを実行しているテストではパケット損失が約4%ですが、実行していないテストではパケット損失が約20%です。
両方のシステムは、次の設定で Xen VM として実行されています。
- インテル Xeon E5-2630 v2 @ 2.60GHz
- 2GBのRAM
- Ubuntu 14.04 x86_64
潜在的な原因としてすでに確認したこと:
- UDP バッファの受信/送信サイズを増やします。
- テストに影響する CPU 負荷。(クライアント側とサーバー側の両方で最大負荷は 40 ~ 50%)
- 'any' ではなく特定のインターフェースで tcpdump を実行します。
- プロミスキャスモードを無効にするには、「-p」を指定して tcpdump を実行します。
- サーバー上でのみ tcpdump を実行しています。これにより、20% のパケット損失が発生しましたが、テストには影響がないようです。
- tcpdump をクライアント上でのみ実行します。これによりパフォーマンスが向上しました。
- netdev_max_backlog と netdev_budget を 2^32-1 に増やしました。違いはありませんでした。
- すべての NIC でプロミスキャス モードのあらゆる設定を試しました (サーバーをオン、クライアントをオフ、サーバーをオフ、クライアントをオン、両方をオン、両方をオフ)。それでも違いはありませんでした。
答え1
tcpdump が動作しているときは、着信フレームの読み取りがかなり迅速になります。私の仮説では、NIC のパケット リング バッファ設定が少し小さいため、tcpdump が動作しているときは、より迅速に空になるのではないかと思います。
Red Hatの加入者であれば、このサポート記事は非常に役立ちます。パケット受信の概要そこには、あなたがまだ考慮していないことがいくつかあります。
システムが IRQ をどのように処理しているかを検討し、ネットワーク インターフェイスの 'dev_weight' を増やすことを検討します (つまり、NIC からユーザー空間に読み取られるパケットが増えます)。アプリケーションがソケットを読み取る頻度を確認します (専用スレッドを使用できますか、スケーラビリティに関する既知の問題/回避策はありますか)。
NIC フレーム バッファを増やします (ethtool
コマンドを使用して、etc. 引数を確認します--set-ring
)。
「受信側のスケーリング」を確認し、トラフィックを読み込むために少なくともその数の受信スレッドを使用します。
tcpdumpはカーネルサポートを使用するなど、何かクールなことをしているのだろうか?パケットリングバッファそうすれば、あなたが見ている動作を説明するのに役立ちます。
答え2
どのようなパワーガバナーを使用していますか? 「オンデマンド」または「保守的」ガバナーで同様の動作を確認しました。
「パフォーマンス」ガバナーを使用し、サーバー BIOS の省電力機能を無効にしてみてください。
何か変わりますか?
答え3
別の方法はip_conntarck
モジュールです。Linux ボックスが新しい接続を受け入れることができるかどうかを確認してください。次の方法でテストします:
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ボックスは新しい接続を受け入れることができません。ip_conntrack
がない場合は、次のように簡単にロードできます。modprobe ip_conntrack
答え4
受信側がパケット レートを処理できないだけだと思いますが、その理由は次のとおりです。
tcpdump を使用するクライアント側ドロップされたパケットの削減: tcpdump はクライアントの速度を低下させ、そのためサーバーはパッカー レートが大幅に低下しますが、それでも部分的には処理できます。この仮説は、クライアントとサーバーの両方の RX/TX パケット カウンターをチェックすることで確認できます。
UDPバッファの受信/送信サイズを増やしたとおっしゃっていましたが、その方法を詳しく教えていただけますか?サーバー上でrmem_maxと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: 特定のインターフェースがカーネルが処理できる速度よりも速くパケットを受信した場合、キューに入れることができるパケットの最大数。