シナリオ私たちは、多くのWindowsクライアントが定期的に大きなファイル(FTP/ SVN/HTTP PUT/SCP)を〜100-160ms離れたLinuxサーバーにアップロードしています。オフィスには1Gbit/sの同期帯域幅があり、サーバーはAWSインスタンスか、米国のDCで物理的にホストされています。
最初の報告では、新しいサーバーインスタンスへのアップロードは、かなり遅いということでした。これはテストでも複数の場所で実証され、クライアントはWindowsシステムからホストへの2-5Mbit/sを安定して見ていました。
AWSインスタンスでiperf -sを実行し、オフィスの**Windows**クライアントで実行しました。 iperf -c 1.2.3.4
です。
[ 5] local 10.169.40.14 port 5001 connected with 1.2.3.4 port 55185
[ 5] 0.0-10.0 sec 6.55 MBytes 5.48 Mbits/sec
iperf -w1M -c 1.2.3.4` とします。
[ 4] local 10.169.40.14 port 5001 connected with 1.2.3.4 port 55239
[ 4] 0.0-18.3 sec 196 MBytes 89.6 Mbits/sec
後者の数値は、その後のテストで大きく変化することがありますが(Vagaries of AWS)、通常は70から130Mbit/sの間であり、私たちのニーズには十分すぎるほどです。このセッションをWiresharkしてみると、以下のようになります。
iperf -c
Windows SYN - Window 64kb, Scale 1 - Linux SYN, ACK: Window 14kb, Scale: 9 (*512)
iperf window scaling with default 64kb Window]1.iperf -c -w1M
Windows SYN - Windows 64kb, Scale 1 - Linux SYN, ACK: Window 14kb, Scale: 9
iperf window scaling with default 1MB Window]2.
リンクがこの高いスループットを維持できることは明らかですが、それを利用するためにはウィンドウサイズを明確に設定しなければならず、現実のほとんどのアプリケーションではそうさせてくれません。TCPハンドシェイクはそれぞれのケースで同じ開始点を使用しますが、強制されたものはスケールします。
逆に、同じネットワーク上のLinuxクライアントから、まっすぐ、iperf -c
(システムのデフォルトである85kbを使用)をすると、次のようになります。[ 5] local 10.169.40.14 port 5001 connected with 1.2.3.4 port 33263
[ 5] 0.0-10.8 sec 142 MBytes 110 Mbits/sec
何も強制しなければ、期待通りにスケールします。これはホップ間やローカルスイッチ/ルーターに原因があるわけではなく、Windows 7と8のクライアントに同様に影響を与えるようです。自動チューニングに関する多くのガイドを読みましたが、これらは通常、ひどいホームネットワークキットを回避するためにスケーリングを完全に無効にすることです。 どなたか、ここで何が起こっているのか、そしてそれを修正する方法を教えていただけませんか?(できれば GPO を使ってレジストリに貼り付けられるようなものがいいのですが)。
問題の AWS Linux インスタンスは、sysctl.conf
で以下のカーネル設定が適用されています。
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 1048576
net.core.wmem_default = 1048576
net.ipv4.tcp_rmem = 4096 1048576 16777216
net.ipv4.tcp_wmem = 4096 1048576 16777216
サーバー側で dd if=/dev/zero | nc
を /dev/null
にリダイレクトして、 iperf
を除外し、他のボトルネックとなりうるものを取り除きましたが、結果はほとんど同じでした。ncftp` (Cygwin, Native Windows, Linux) でのテストは、それぞれのプラットフォームで上記の iperf テストとほぼ同じようにスケールします。
この中でもう一つ、関連しそうな一貫したものを発見しました。 。 これは1MBのキャプチャの最初の1秒間を拡大したものです。ウィンドウが拡大され、バッファが大きくなると、スロースタートが動作しているのがわかります。そして、デフォルトのウィンドウiperfテストが永遠に平坦になるポイントに、~0.2sの小さなプラトーがあります。もちろん、このテストでは、もっと大きな高さにスケーリングしますが、その前にスケーリングにこのような間があるのは不思議です(値は 1022bytes * 512 = 523264)。
様々な回答についてフォローアップしています。
カイルさんの提案にしたがって、ctcpを有効にして、煙突オフロードを無効にしました。 TCPグローバルパラメータ
----------------------------------------------
Receive-Side Scaling State : enabled
Chimney Offload State : disabled
NetDMA State : enabled
Direct Cache Acess (DCA) : disabled
Receive Window Auto-Tuning Level : normal
Add-On Congestion Control Provider : ctcp
ECN Capability : disabled
RFC 1323 Timestamps : enabled
Initial RTO : 3000
Non Sack Rtt Resiliency : disabled
しかし、悲しいことに、スループットに変化はありません。 私はここで原因/結果の質問を持っています、しかし。グラフはサーバからクライアントへのACKで設定されたRWINの値です。Windowsクライアントでは、クライアントの限られたCWINがバッファを満たすことを妨げるので、Linuxはこの値をその低いポイント以上にスケーリングしないと考えるのは正しいのでしょうか?Linuxが人為的にRWINを制限している他の理由があるのでしょうか? 注:念のためECNをオンにしてみましたが、特に変化はありませんでした。
ヒューリスティックとRWINのオートチューニングを無効にしても、変化はありませんでした。Intelのネットワークドライバを最新(12.10.28.0)に更新し、viadevice managerタブのfuncioanlity tweaksを公開するソフトを使いました。カードは82579V Chipset on-board NIC - (I'm going to do some more test from clients with realtek or other vendors)である。 NICに焦点を当てると、以下のことを試してみました。
Linuxサーバ側を排除するために、Server 2012R2インスタンスを立ち上げ、 iperf
(cygwin binary) と NTttcp を使用してテストを繰り返しました。
iperfでは、明示的に
-w1mを指定しないと、~5Mbit/s を超える接続はできませんでした。(ちなみに、91msのレイテンシで〜5MbitsのBDPはほぼ正確に64kbであることが確認できました。限界を見抜く...) ntttcpのバイナリは、このような制限を示しました。サーバ側で
ntttcpr -m 1,0,1.2.3.5を、クライアント側で
ntttcp -s -m 1,0,1.2.3.5 -t 10` を使うと、スループットがかなり良くなりました。
Copyright Version 5.28
Network activity progressing...
Thread Time(s) Throughput(KB/s) Avg B / Compl
====== ======= ================ =============
0 9.990 8155.355 65536.000
##### Totals: #####
Bytes(MEG) realtime(s) Avg Frame Size Throughput(MB/s)
================ =========== ============== ================
79.562500 10.001 1442.556 7.955
Throughput(Buffers/s) Cycles/Byte Buffers
===================== =========== =============
127.287 308.256 1273.000
DPCs(count/s) Pkts(num/DPC) Intr(count/s) Pkts(num/intr)
============= ============= =============== ==============
1868.713 0.785 9336.366 0.157
Packets Sent Packets Received Retransmits Errors Avg. CPU %
============ ================ =========== ====== ==========
57833 14664 0 0 9.476
8MB/sは、私がiperf
で明示的に大きなウィンドウで取得していたレベルまで上げています。しかし、奇妙なことに、1273のバッファで80MB = 64kBのバッファです。さらにwiresharkで調べてみると、サーバから戻ってくるRWINは良好で可変であり(Scale factor 256)、クライアントもそれを満たしているようです; おそらくntttcpは送信ウィンドウを誤って報告しているのでしょう。
karyhead' の要求により、さらにいくつかのテストを行い、ここにいくつかのキャプチャを作成しました。 https://www.dropbox.com/s/dtlvy1vi46x75it/iperf%2Bntttcp%2Bftp-pcaps-2014-07-03.zip
iperf
を実行。ひとつは 128k ソケットサイズとデフォルトの 64k ウィンドウ (再び ~5Mbit/s に制限) で、もうひとつは 1MB の送信ウィンドウとデフォルトの 8kb ソケットサイズです。(もっと高いスケール)ntttcp
トレースです。Note: NTttcpはテスト接続を開く前に、ポート6001で何か奇妙なことをします。何が起こっているのかよくわかりません。ncftp
を使用して、20MBの /dev/urandom
をほぼ同じLinuxホスト (1.2.3.6) にアップロードしています。ここでも制限があります。WindowsのFilezillaを使っても同じようなパターンです。
iperf` のバッファ長を変更すると、タイムシーケンスグラフに予想された違い(より多くの垂直セクション)が生じますが、実際のスループットは変わりません。Windows 7/8クライアントでCompound TCP (CTCP)を有効にしてみましたか?
ご一読ください。
高BDP伝送のための送信側性能の向上」をご覧ください。
http://technet.microsoft.com/en-us/magazine/2007.01.cableguy.aspx
...
これらのアルゴリズムは、小さなBDPと小さな受信ウィンドウでうまく機能します。 サイズではうまくいきます。しかし、大きな受信ウィンドウサイズを持つTCP接続がある場合、このアルゴリズムはうまく機能しません。 しかし、受信ウィンドウサイズが大きく、BDPが大きいTCP接続の場合、例えば、2つのサーバ間でデータをレプリケートするような場合、このアルゴリズムはうまく機能します。 100msの往復で高速なWANリンクを介して配置された2つのサーバ間でデータを複製する場合など、受信ウィンドウサイズが大きく、BDPが大きいTCP接続の場合 これらのアルゴリズムは、送信ウィンドウを十分に速く増加させることができません。 接続の帯域幅を十分に利用することができません。
このような状況でTCPコネクションの帯域幅をより有効に活用するために、次世代TCPコネクションサーバが開発されました。 次世代TCP/IPスタックには、Compound TCP(CTCP)が含まれています。 (CTCP)があります。CTCPは、より積極的に送信ウィンドウを増加させることができます。 受信ウィンドウサイズとBDPが大きいコネクションに対して、より積極的に送信ウィンドウを増加させます。CTCPは以下のことを試みます。 CTCPは、遅延を監視することによって、これらのタイプの接続のスループットを最大化しようとします。 gt;変動と損失を監視することにより、これらのタイプの接続におけるスループットの最大化を試みます。さらに、CTCPは、その動作が次のような悪影響を与えないようにします。 他のTCPコネクションに悪影響を与えないようにします。
...
CTCP は、Windows Server 2008 を実行しているコンピュータではデフォルトで有効になっており、Windows Vista を実行しているコンピュータではデフォルトで無効になっています。 Windows Vista が動作しているコンピュータでは、デフォルトで無効になっています。CTCP を有効にするには、
netsh' を実行します。 netsh interface tcp set global congestionprovider=ctcp
コマンドで有効にできます。CTCP を無効にするには netsh interface tcp set global congestionprovider=none` コマンドを使用します。
2014/6/30編集
で、CTCPが本当にquot;on"になっているかどうか確認できます。
> netsh int tcp show global
すなわち
。
POは言った。
私が正しく理解しているならば、この設定は、最大サイズではなく、輻輳ウィンドウを拡大するレートを増加させます。 この設定は、輻輳ウィンドウの最大サイズではなく、輻輳ウィンドウを拡大する率を増加させます。 到達可能な最大サイズではなく、拡大される速度*を増加させます。
CTCPは積極的に送信ウィンドウを増加させる
http://technet.microsoft.com/en-us/library/bb878127.aspx
複合TCP
送信側のTCPピアがネットワークを圧迫しないようにする既存のアルゴリズムは、スロースタートと輻輳(ふくそう)です。 スロースタートや輻輳回避と呼ばれるものです。 回避と呼ばれています。これらのアルゴリズムは、送信者が送信できるセグメントの量を増加させます。 これらのアルゴリズムは、最初にデータを送信するとき、送信ウィンドウとして知られる、送信者が送信できるセグメントの量を増やします。 これらのアルゴリズムは、送信者が送信ウィンドウとして知られている、最初にデータを送信するときと、失われたセグメントから回復するときに、送信できるセグメントの量を増やします。スロースタート 送信ウィンドウを、以下のいずれかの場合に、1セグメント分増加させます。 Windows XPやWindows Server 2003のTCPでは、確認応答セグメントを受信するごとに、送信ウィンドウを1つ増やします。 Server 2003のTCPの場合)、または確認応答があったセグメントごとに、送信ウィンドウを1つ分増やします。 VistaとWindows Server 2008のTCPの場合)。輻輳回避は、送信ウィンドウを1つ分増やします。 送信ウィンドウは、1つのフルウィンドウのデータに対して、1つのフルTCPセグメントで構成されます。 確認応答が行われます。
これらのアルゴリズムは、LANのメディア速度や、より小さいTCPウィンドウサイズでうまく機能します。 これらのアルゴリズムは、LANのメディア速度や、より小さなTCPウィンドウサイズではうまく機能します。しかし、受信ウィンドウサイズが大きいTCP接続の場合、このアルゴリズムはうまく機能しません。 gt;ウィンドウサイズが大きく、帯域と遅延の積が大きい(帯域が広く、遅延が大きい)TCP接続の場合。 例えば、高速なWANに設置された2つのサーバ間でデータを複製するような、大きな受信ウィンドウサイズと大きな帯域-遅延積(高帯域と高遅延)を持つTCP接続の場合。 例えば、往復時間が100msの高速WANリンクを介してデータを複製する場合、これらの 送信ウィンドウを高速に増加させることができないため、帯域幅を十分に利用することができません。 接続の帯域幅を十分に利用することができません。例えば、1ギガビットイーサネットの場合 GbpsのWANリンクで、ラウンドトリップタイム(RTT)が100msの場合、以下のようなことが起こり得ます。 送信ウィンドウが最初にまで増加するのに1時間かかることがあります。 受信機によってアドバタイズされる大きなウィンドウサイズまで増加し、回復するまでに最大1時間かかります。 セグメントを失うことがあります。
このような状況でTCPコネクションの帯域幅をよりよく利用するために、次世代TCPコネクションは、以下のような機能を備えています。 次世代TCP/IPスタックには、Compound TCP (CTCP)が含まれています。 (CTCP)があります。CTCPは、より積極的に送信ウィンドウを増加させます。 受信ウィンドウサイズが大きく、帯域遅延が大きい接続の場合、CTCPはより積極的に送信ウィンドウを増加させます。 製品です。CTCP は、これらのタイプの接続のスループットを最大化することを試みます。 遅延の変動や損失を監視することによって、これらのタイプの接続のスループットを最大化しようとします。また、CTCPは その動作が他のTCP接続に悪影響を与えないようにします。 接続に悪影響を与えないようにします。 となります。 マイクロソフト社内で実施したテストでは、大容量ファイルのバックアップ時間が約半分に短縮されました。 RTTが50msの1Gbps接続では、ほぼ半分に短縮されました。 帯域幅遅延製品が大きい接続では、さらに優れたパフォーマンスを発揮することができます。 パフォーマンスを向上させることができます。CTCPと受信ウィンドウの自動チューニングは、リンクの利用率を向上させるために連動しています。 リンクの利用率を高め、大幅な性能向上を実現します。 帯域遅延積が大きい接続では、大幅な性能向上が期待できます。
TCPには2つのウィンドウがあります。
あなたが提供したキャプチャファイルで。受信バッファが決してオーバーフローしていないことがわかります。
。
***私の分析では、送信者は送信ウィンドウ(別名、輻輳制御ウィンドウ)が受信者のRWINを満たすのに十分な大きさに開いていないため、十分な速さで送信していません。つまり、受信者は「もっとよこせ」と言い、Windowsが送信者である場合、十分な速度で送信できていないのです。
このことは、上のグラフでRWINが開いたままになっていることからもわかります。往復時間が0.09秒、RWINが50万バイトの場合、帯域遅延積による最大スループットは (500000/0.09) * 8 =~ 42 Mbit/sと予想できます(WindowsからLinuxへのキャプチャでは、およそ5しか得られませんが)。
わからない‼インターフェイス tcp set global congestionprovider=ctcp` は、送信ウィンドウ(輻輳ウィンドウの別称)を増やすので、私には正しいことのように聞こえますが。それがうまくいっていないとおっしゃいました。ということで、念のため。
1.これを有効にした後、リブートしましたか? 2.2. Chimneyオフロードはオンになっていますか?もしそうなら、実験的にそれをオフにしてみてください。もし、送信ウィンドウの制御がその一つであれば、輻輳プロバイダが有効であっても効果がないのかもしれませんね...。あくまで推測ですが...。 3.あと、これはwindows7以前の話かもしれませんが、HKEY_LOCAL_MACHINE-System-CurrentControlSet-Services-AFD-ParametersにDefaultSendWindowとDefaultReceiveWindowという二つのレジストリキー追加して弄ってみてはいかがでしょう?もし、これらも動作するなら、おそらくctcpをオフにする必要があります。 4. netsh interface tcp show heuristics`をチェックしてみてください。私はそれがRWINかもしれないと思うのですが、それは言っていないので、送信ウィンドウに影響を与えるかもしれないので、それを無効にしたり、有効にしたりして遊んでみてください。 5.5. また、あなたのテストクライアントのドライバが最新であることを確認してください。もしかしたら、何かが壊れているだけかもしれません。
ネットワークドライバが書き換えや修正を行っている可能性を排除するために、オフロード機能をすべてオフにした状態で、これらの実験を行ってみてください(オフロードを無効にしている間はCPUを監視してください)。TCP_OFFLOAD_STATE_DELEGATED struct]2 は、少なくとも CWnd オフロードが可能であることを暗示しているようです。
ここには@Patと@Kyleによるいくつかの素晴らしい情報があります。Kyle' の TCP 受信と送信のウィンドウについての 説明 には間違いなく注意を払ってください。さらに問題を混乱させるために、iperf は -w
設定で "TCP window" という用語を使っていますが、これは受信、送信、あるいは全体のスライディングウィンドウに関して曖昧な用語です。この設定は、実際には -c
(クライアント) インスタンスのソケット送信バッファと -s
(サーバ) インスタンスのソケット受信バッファを設定するものです。src/tcp_window_size.c` にある。
if ( !inSend ) {
/* receive buffer -- set
* note: results are verified after connect() or listen(),
* since some OS's don't show the corrected value until then. */
newTCPWin = inTCPWin;
rc = setsockopt( inSock, SOL_SOCKET, SO_RCVBUF,
(char*) &newTCPWin, sizeof( newTCPWin ));
} else {
/* send buffer -- set
* note: results are verified after connect() or listen(),
* since some OS's don't show the corrected value until then. */
newTCPWin = inTCPWin;
rc = setsockopt( inSock, SOL_SOCKET, SO_SNDBUF,
(char*) &newTCPWin, sizeof( newTCPWin ));
}
Kyle が言っているように、問題は Linux マシンの受信ウィンドウではなく、送信者が送信ウィンドウを十分に開いていないことです。送信ウィンドウが十分に開いていないのではなく、64Kに制限されているのです。
Windows 7のデフォルトのソケットバッファサイズは64kです。以下は、ソケットバッファサイズとスループットの関係について、MSDNのドキュメントに記載されている内容です。
Windowsのソケットを使用してTCP接続でデータを送信する場合、次のことが重要です。
十分な量の未処理データ(送信済みでありながら
を十分に残しておくことが重要です。
スループットを向上させることができます。最高のスループットを得るための未処理データ量の理想的な値は、次のとおりです。
TCP接続で最高のスループットを達成するための未処理データ量の理想的な値を、理想的な送信残量(ISG)と呼びます。
ISB(Send Backlog)サイズと呼びます。ISB値は、以下の関数で表されます。
TCP接続の帯域幅-遅延積と、受信側の
ISB値は、TCP接続の帯域幅と遅延の積と、受信側の広告受信ウィンドウ(一部、ネットワークの輻輳量も含む)の関数です。
ということです。)
さて、ぼちぼちと、いきますか。
ブロッキングまたはノンブロッキングの送信要求を一度に実行するアプリケーションは、一般的に、送信要求を処理するために、送信ウィンドウを使用します。
一般的には、Winsockによる内部送信バッファリングに依存し、適切なスループットを達成します。
まともなスループットを達成するために、Winsockによる内部送信バッファリングに依存するのが一般的です。ある接続の送信バッファの上限は、以下の通りです。
SO_SNDBUF ソケットオプションで制御されます。ブロッキング送信と
ブロッキング送信方式とノンブロッキング送信方式では、送信バッファの上限は、送信バッファの上限を決定します。
送信バッファの制限は、TCPで未処理のデータを保持する量を決定します。接続のISB値が
接続のISB値が送信バッファの上限値より大きい場合、その接続で達成されるスループットは、送信バッファの上限値より小さくなります。
接続のISB値が送信バッファの制限値よりも大きい場合、その接続で達成されるスループットは最適ではありません。
64kウィンドウを使用した直近のiperfテストの平均スループットは5.8Mbpsです。これは、WiresharkのStatistics > Summary**によるもので、すべてのビットをカウントしています。iperfはTCPデータスループットをカウントしているようで、5.7Mbpsでした。FTPテストでも同様に、〜5.6Mbpsのパフォーマンスが確認できます。
64kの送信バッファと91msのRTTでの理論上のスループットは...5.5Mbpsです。十分近い値です。
1MBウィンドウのiperfテストを見てみると、tputは88.2Mbps(TCPデータだけの場合は86.2Mbps)です。1MBウィンドウでの理論上のtputは87.9Mbpsです。ここでも、政府の仕事としては十分に近い。
このことからわかるのは、送信ソケットのバッファが直接送信ウィンドウを制御し、それが相手側からの受信ウィンドウと相まってスループットを制御しているということです。広告の受信ウィンドウは余裕があるので、我々は受信機によって制限されていない。
ちょっと待ってください、このオートチューニングのビジネスはどうなんですか?Windows 7では、そのようなことは自動的に処理されないのですか?前述のとおり、Windows は受信ウィンドウの自動スケーリングを行いますが、送信バッファも動的に処理することができます。MSDN のページに戻りましょう。
TCP の動的な送信バッファリングは、Windows 7 と Windows Server 2008 R2 で追加されました。
Server 2008 R2 で追加されました。デフォルトでは、TCPの動的な送信バッファリングは有効です。
アプリケーションがストリームに SO_SNDBUF ソケットオプションを設定しない限り、TCP の動的送信バッファリングは有効です。
ソケットを使用します。
iperfは-w
オプションを使用する場合、SO_SNDBUF
を使用するので、動的な送信バッファリングは無効になります。しかし、-w
を使用しない場合、SO_SNDBUF
は使用されません。動的な送信バッファリングは、デフォルトでオンになっているはずですが、確認することができます。
netsh winsock show autotuning
で無効化できるとドキュメントに書いてあります。
netsh winsock set autotuning off
しかし、これではうまくいきませんでした'。レジストリを変更して、これを0にする必要がありました。 HKEY_LOCAL_MACHINE_SYSTEMのCurrentControlSetのThinkServicesのThinkAFDParametersのThinkDynamicSendBufferDisable`のように。 これを無効にしても解決しないと思いますが、ご参考までに。 受信ウィンドウに十分なスペースがあるLinuxマシンにデータを送るとき、なぜ送信バッファはデフォルトの64kを超えるスケーリングができないのですか?いい質問ですね。LinuxカーネルはTCPスタックを自動チューニングしています。T-PainとKanyeが一緒にオートチューンのデュエットをするように、それは良い音ではないかもしれません。おそらく、これら2つのオートチューニングTCPスタックが互いに会話する際に、何らかの問題があるのでしょう。 別の人はあなたと同じような問題を抱えていて、レジストリを編集してデフォルトの送信バッファサイズを大きくすることで解決しました。残念ながら、それはもう機能しないようです。少なくとも、私が試したときには機能しませんでした。 **この時点で、私はそれが制限された要因は、Windowsホスト上の送信バッファサイズであることは明らかだと思います。 できることは