Throughput TCP lebih rendah dari server 1Gbps dari server 100Mbps melalui RTT besar

9

Kami memiliki infrastruktur yang didistribusikan di beberapa lokasi utama di seluruh dunia - Singapura, London dan Los Angeles. RTT antara dua lokasi lebih dari> 150 ms.

Kami baru saja memutakhirkan semua server untuk menggunakan tautan 1Gbps (dari 100Mbps). Kami telah menjalankan beberapa pengujian berbasis TCP antara server di lokasi yang berbeda dan telah melihat beberapa hasil yang mengejutkan. Hasil ini sepenuhnya dapat diulang.

  1. Los Angeles (100Mbps) ke London (100Mbps): ~ 96Mbps throughput
  2. Los Angeles (100Mbps) ke London (1Gbps): ~ 96Mbps throughput
  3. Los Angeles (1Gbps) ke London (100Mbps): 10-40Mbps throughput (volatile)
  4. Los Angeles (1Gbps) ke London (1Gbps): 10-40Mbps throughput (volatile)
  5. Los Angeles (1Gbps) ke Los Angeles (1Gbps):> 900Mbps throughput

Tampaknya setiap kali pengirim beroperasi pada 1Gbps, throughput kami sangat signifikan selama tautan yang panjang.

Pendekatan pengujian sebelumnya sangat sederhana - Saya hanya menggunakan cURL untuk mengunduh biner 1GB dari server target (jadi dalam kasus di atas, klien cURL berjalan di server London dan unduhan dari LA, sehingga LA adalah pengirim) . Ini menggunakan koneksi TCP tunggal tentunya.

Mengulangi tes yang sama pada UDP menggunakan iperf, masalahnya hilang!

  1. Los Angeles (100Mbps) ke London (100Mbps): ~ 96Mbps throughput
  2. Los Angeles (100Mbps) ke London (1Gbps): ~ 96Mbps throughput
  3. Los Angeles (1Gbps) ke London (100Mbps): ~ 96Mbps throughput
  4. Los Angeles (1Gbps) ke London (1Gbps):> throughput 250Mbps

Ini menunjuk tepat pada beberapa masalah konfigurasi TCP atau NIC / port di mata saya.

Kedua server menjalankan CentOS 6.x, dengan TCP cubic. Keduanya memiliki jendela kirim & terima TCP maksimum 8MB, dan cap waktu TCP dan ucapan terima kasih selektif diaktifkan. Konfigurasi TCP yang sama digunakan dalam semua kasus uji. Konfigurasi TCP lengkap ada di bawah:

net.core.somaxconn = 128
net.core.xfrm_aevent_etime = 10
net.core.xfrm_aevent_rseqth = 2
net.core.xfrm_larval_drop = 1
net.core.xfrm_acq_expires = 30
net.core.wmem_max = 8388608
net.core.rmem_max = 8388608
net.core.wmem_default = 131072
net.core.rmem_default = 131072
net.core.dev_weight = 64
net.core.netdev_max_backlog = 1000
net.core.message_cost = 5
net.core.message_burst = 10
net.core.optmem_max = 20480
net.core.rps_sock_flow_entries = 0
net.core.netdev_budget = 300
net.core.warnings = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_retrans_collapse = 1
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_synack_retries = 5
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_tw_buckets = 262144
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_fin_timeout = 60
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_abort_on_overflow = 0
net.ipv4.tcp_stdurg = 0
net.ipv4.tcp_rfc1337 = 0
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_orphan_retries = 0
net.ipv4.tcp_fack = 1
net.ipv4.tcp_reordering = 3
net.ipv4.tcp_ecn = 2
net.ipv4.tcp_dsack = 1
net.ipv4.tcp_mem = 1528512      2038016 3057024
net.ipv4.tcp_wmem = 4096        131072  8388608
net.ipv4.tcp_rmem = 4096        131072  8388608
net.ipv4.tcp_app_win = 31
net.ipv4.tcp_adv_win_scale = 2
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_frto = 2
net.ipv4.tcp_frto_response = 0
net.ipv4.tcp_low_latency = 0
net.ipv4.tcp_no_metrics_save = 0
net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_tso_win_divisor = 3
net.ipv4.tcp_congestion_control = cubic
net.ipv4.tcp_abc = 0
net.ipv4.tcp_mtu_probing = 0
net.ipv4.tcp_base_mss = 512
net.ipv4.tcp_workaround_signed_windows = 0
net.ipv4.tcp_dma_copybreak = 4096
net.ipv4.tcp_slow_start_after_idle = 1
net.ipv4.tcp_available_congestion_control = cubic reno
net.ipv4.tcp_allowed_congestion_control = cubic reno
net.ipv4.tcp_max_ssthresh = 0
net.ipv4.tcp_thin_linear_timeouts = 0
net.ipv4.tcp_thin_dupack = 0

Terlampir adalah beberapa gambar grafik IO wireshark dari beberapa kasus uji (maaf, saya belum dapat mengirim gambar langsung):

Test case 1 (100Mbps -> 100Mbps) - transfer halus yang bagus. Tidak ada kerugian dalam penangkapan. - http://103.imagebam.com/download/dyNftIGh-1iCFbjfMFvBQw/25498/254976014/100m.png

Test case 3 (1Gbps -> 100Mbps) - transfer votaile, membutuhkan waktu lama untuk mencapai kecepatan apa pun - tidak pernah mendekati 100Mbps. Namun tidak ada kerugian / transmisi ulang dalam penangkapan! - http://101.imagebam.com/download/KMYXHrLmN6l0Z4KbUYEZnA/25498/254976007/1g.png

Jadi secara ringkas, ketika tautan panjang digunakan dengan koneksi 1Gbps, kami mendapatkan throughput TCP yang jauh lebih rendah daripada ketika kami menggunakan koneksi 100Mbps.

Saya sangat menghargai beberapa petunjuk dari pakar TCP di luar sana!

Terima kasih!

UPDATE (2013-05-29):

Kami telah memecahkan masalah dengan test case # 4 di atas (pengirim 1Gbps, penerima 1Gbps, pada RTT besar). Kami sekarang dapat menekan ~ 970Mbps dalam beberapa detik sejak dimulainya transfer. Masalahnya tampaknya adalah saklar yang digunakan dengan penyedia hosting. Pindah ke yang berbeda memecahkannya.

Namun, uji kasus # 3 sebagian besar tetap bermasalah. Jika kita memiliki penerima yang berjalan pada 100Mbps dan pengirim di 1Gbps, maka kita melihat sekitar 2-3 menit menunggu penerima mencapai 100Mbps (tetapi sekarang mencapai tingkat penuh, tidak seperti sebelumnya). Segera setelah kami menurunkan pengirim ke 100Mbps atau menambah penerima ke 1Gbps, maka masalahnya hilang dan kami dapat meningkatkan kecepatan penuh dalam satu atau dua detik.

Alasan yang mendasarinya adalah bahwa kita melihat kerugian, tentu saja, segera setelah transfer dimulai. Namun, ini tidak sesuai dengan pemahaman saya tentang bagaimana start lambat bekerja; kecepatan antarmuka seharusnya tidak ada kaitannya dengan ini, karena harus diatur oleh ACK dari penerima.

Saran, terima kasih, terima kasih! Jika saya dapat menawarkan hadiah di sini, saya akan melakukannya!

Sam
sumber
1
Apakah Anda menggunakan TCP offload pada NIC di kedua sisi? Apakah penggunaan TCP offload Anda bervariasi dari 100M ke 1G NIC? Jika itu digunakan dalam salah satu kasus uji, mungkin perlu mengulangi tes dengan yang dinonaktifkan hanya untuk melihat apakah mesin TCP offload pada NIC 100M mungkin menghalangi kinerja komunikasi 1G (komentar ini sengaja dibuat hand-wavey hanya untuk memunculkan TOE)
FliesLikeABrick
Pertanyaan bagus! Offload segmentasi TCP dinonaktifkan di kedua ujungnya. Offload segmentasi generik diaktifkan di kedua ujungnya. Saya juga mengulanginya dengan TSO diaktifkan, dan itu tidak membuat perbedaan yang nyata.
Sam
Coba nonaktifkan segmentasi segmentasi generik, setidaknya di sisi 100M, dan ulangi tes Anda
FliesLikeABrick
Terima kasih atas sarannya, tetapi tidak ada sukacita - hasil yang sama dengan gso on atau off di kedua sisi.
Sam
1Gbps pada 150ms + memberikan Produk Penundaan Bandwidth yang sangat besar, lebih dari 18Mb. Apa yang terjadi jika Anda menaikkan buffer socket Anda? tcp_*mem = 4096 1048576 33554432Anda belum mengaktifkan Jumbo Frames pada tautan 1Gbps, bukan? Itu bisa menyebabkan fragmentasi di suatu tempat.
suprjami

Jawaban:

1

Masalah utama adalah keterlambatan WAN besar. Akan sangat buruk jika paket acaknya juga hilang.

1, tcp_mem juga perlu diatur besar untuk mengalokasikan lebih banyak memori. Misalnya, tetapkan sebagai net.ipv4.tcp_mem = 4643328 6191104 9286656

2, Anda dapat menangkap paket melalui wireshark / tcpdump selama beberapa menit lalu menganalisis apakah paket acaknya hilang. Anda juga dapat mengunggah file paket jika mau.

3, Anda dapat mencoba untuk menyetel parameter tcp lainnya Eg. set tcp_westwood = 1 dan tcp_bic = 1

HarryREN
sumber
Terima kasih, tapi kami sudah mencoba semua itu. Penundaan WAN bukan masalah - kita dapat menekan 100Mbps segera jika kita menggunakan port 100Mbps, tetapi segera setelah satu perubahan ke 1Gbps maka kita bersulang.
Sam
1

Terpecahkan! Untuk perincian lengkap, lihat http://comments.gmane.org/gmane.linux.drivers.e1000.devel/11813

Singkatnya, tampaknya server yang terhubung 1Gbps akan mengirimkan ledakan lalu lintas selama fase pertumbuhan eksponensial TCP yang akan membanjiri buffer di beberapa perangkat perantara (siapa yang tahu apa). Ini menyisakan dua opsi:

1) Hubungi setiap operator jaringan perantara dan minta mereka untuk mengkonfigurasi buffer yang sesuai untuk memungkinkan bandwidth dan RTT yang saya inginkan. Sangat tidak mungkin! 2) Batasi semburan.

Saya memilih untuk membatasi setiap aliran TCP untuk beroperasi pada 100Mbps paling banyak. Angka di sini cukup sewenang-wenang - Saya memilih 100Mbps murni karena saya tahu jalur sebelumnya dapat menangani 100Mbps dan saya tidak perlu lagi untuk aliran individu .

Semoga ini bisa membantu seseorang di masa depan.

Sam
sumber
0

Mengulangi tes yang sama pada UDP menggunakan iperf, masalahnya hilang!

Los Angeles (1Gbps) ke London (1Gbps):> throughput 250Mbps

Masalahnya tampaknya tidak hilang, kira-kira 75% dari paket Anda semakin turun? Jika TCP berjalan lambat setiap saat, bandwidth rata-rata Anda mungkin agak rendah.

Btw, apakah Anda memiliki tolok ukur untuk London ke LA, dan London ke London?

Jens Timmerman
sumber
Saya lupa menyebutkan bahwa klien itu lambat ... Jika kami ulangi dengan dua klien cepat, maka kami menekan ~ 970Mbps dua arah.
Sam