考えられるネットワークのボトルネックについて詳しく理解するために、簡単なUDPサーバープログラムを作成しました。
UDPサーバー:UDPソケットを作成し、指定されたポートとアドレスにバインドして、ソケットファイル記述子をepollインタレストリストに追加します。次に、そのepollは着信パケットを待ちます。着信パケット(EPOLLIN)を受信すると、パケットを読み取り、受信したパケットの長さを出力するだけです。とてもシンプルですよね:)
UDPクライアント:以下に示すようにhpingを使用しました:
hping3 192.168.1.2 --udp -p 9996 --flood -d 100
毎秒100パケットでudpパケットを送信すると、UDPパケットの損失は見つかりません。しかし、(上記のコマンドに示されているように)udpパケットをフラッディングすると、重大なパケット損失が発生します。
Test1:26356パケットがUDPクライアントからフラッディングされると、サンプルプログラムは12127パケットのみを受信し、残りの14230パケットは/に示すようにカーネルによってドロップされます。 proc/net/snmp出力。
cat/proc/net/snmp | grep Udp:
Udp:InDatagrams NoPortsInErrorsOutDatagramsRcvbufErrorsSndbufErrors
UDP:12372 014230218142300
Test1の場合、パケット損失率は約53%です。
クライアント側とサーバー側の両方で「ethtool-SethX」コマンドを使用して、ハードウェアレベルで大きな損失がないことを確認しましたが、applnレベルでは、上記のように53%の損失が見られます。
したがって、パケット損失を減らすために、私はこれらを試しました:
- renice コマンドを使用して、サンプルプログラムの優先度を上げました。
-受信バッファサイズの増加(システムレベルとプロセスレベルの両方)
優先度を-20に上げます。
renice -20 2022
2022(プロセスID)古い優先度0、新しい優先度-20
受信bufサイズを16MBに増やします。
プロセスレベルで:
int sockbufsize = 16777216;
setsockopt(sockfd、SOL_SOCKET、SO_RCVBUF、(char *)&sockbufsize、(int)sizeof(sockbufsize))
カーネルレベルで:
cat/proc/sys/net/core/rmem_default
16777216
cat/proc/sys/net/core/rmem_max
16777216
これらの変更後、Test2を実行しました。
Test2:1985076パケットがUDPクライアントからフラッディングされると、サンプルプログラムは1848791パケットを受信し、残りの136286パケットは/ procに示すようにカーネルによってドロップされます。/net/snmp出力。
cat/proc/net/snmp | grep Udp:
Udp:InDatagrams NoPortsInErrorsOutDatagramsRcvbufErrorsSndbufErrors
UDP:1849064 01362862360
Test2の場合、パケット損失率は6%です。
パケット損失が大幅に削減されます。しかし、私は次の質問があります:
あなたの助けと時間をありがとう!!!
Linuxカーネルのネットワークスタックを調整してパケットドロップを減らすには、ドライバーからネットワークに至るまでの調整オプションがたくさんあるため、少し複雑です。スタック。
長いブログ投稿 すべてのチューニングパラメータを上から下に説明し、/proc/net/snmp
の各フィールドの意味を説明して、これらのエラーが発生している理由を理解できるようにしました。見てください、それはあなたがあなたのネットワークを0に落とすのを助けるべきだと思います。
ハードウェアレベルでドロップがない場合は、ほとんどがメモリの問題であるはずです。カーネル構成パラメータを微調整して0ドロップに到達できるようにする必要があります(明らかに、受信しているネットワークトラフィックに対して適切なバランスの取れたハードウェアが必要です)。 )。
私はあなたが欠けていると思います netdev_max_backlog これは着信パケットにとって重要です:
インターフェイスがカーネルが処理できるよりも速くパケットを受信したときに、INPUT側でキューに入れられるパケットの最大数。
InErrorsは次のもので構成されています。
したがって、バッファオーバーフローの問題(RcvbufErrorsは0)が修正され、チェックサムが正しくないパケットが残っていると思います。