Tuning parameter perutean IP Linux - secret_interval dan tcp_mem

30

Kami memiliki sedikit masalah failover dengan salah satu HAProxy VM kami hari ini. Ketika kami menggali, kami menemukan ini:

26 Jan 07:41:45 kernel haproxy2: [226818.070059] __ratelimit: 10 callback ditekan
26 Jan 07:41:45 kernel haproxy2: [226818.070064] Kehabisan memori soket
26 Jan 07:41:47 kernel haproxy2: [226819.560048] Kehabisan memori soket
26 Jan 07:41:49 kernel haproxy2: [226822.030044] Kehabisan memori soket

Yang, per tautan ini , tampaknya berkaitan dengan pengaturan default rendah untuk net.ipv4.tcp_mem. Jadi kami meningkatkannya 4x dari standarnya (ini adalah Server Ubuntu, tidak yakin apakah rasa Linux itu penting):

nilai saat ini adalah: 45984 61312 91968
nilai baru adalah: 183936 245248 367872

Setelah itu, kami mulai melihat pesan kesalahan aneh:

26 Jan 08:18:49 haproxy1 kernel: [2291.579726] Rute rantai hash terlalu lama!
26 Jan 08:18:49 kernel haproxy1: [2291.579732] Sesuaikan secret_interval Anda!

Shh .. ini rahasia !!

Ini tampaknya ada hubungannya dengan /proc/sys/net/ipv4/route/secret_intervaldefault ke 600 dan mengontrol pembilasan berkala cache rute

The secret_intervalmenginstruksikan kernel seberapa sering untuk menerbangkan SEMUA entri rute hash terlepas dari berapa baru / lama mereka. Di lingkungan kita ini umumnya buruk. CPU akan sibuk membangun kembali ribuan entri per detik setiap kali cache dihapus. Namun kami menetapkan ini untuk dijalankan sekali sehari untuk menjaga agar memori tidak hilang (meskipun kami belum pernah memilikinya).

Meskipun kami senang mengurangi ini, rasanya aneh untuk merekomendasikan menjatuhkan seluruh cache rute secara berkala , daripada hanya mendorong nilai-nilai lama keluar dari cache rute lebih cepat.

Setelah beberapa penyelidikan, kami menemukan /proc/sys/net/ipv4/route/gc_elasticityyang tampaknya menjadi pilihan yang lebih baik untuk menjaga ukuran tabel rute tetap di cek:

gc_elasticitydapat digambarkan sebagai kedalaman rata-rata ember yang akan diterima kernel sebelum mulai entri hash rute yang kedaluwarsa. Ini akan membantu mempertahankan batas atas rute aktif.

Kami menyesuaikan elastisitas dari 8 menjadi 4, dengan harapan cache rute pemangkasan itu sendiri lebih agresif. Tidak secret_intervalterasa benar bagi kita. Tetapi ada banyak pengaturan dan tidak jelas yang benar-benar cara yang tepat untuk pergi ke sini.

  • / proc / sys / net / ipv4 / route / gc_elasticity (8)
  • / proc / sys / net / ipv4 / route / gc_interval (60)
  • / proc / sys / net / ipv4 / route / gc_min_interval (0)
  • / proc / sys / net / ipv4 / route / gc_timeout (300)
  • / proc / sys / net / ipv4 / route / secret_interval (600)
  • / proc / sys / net / ipv4 / route / gc_thresh (?)
  • rhash_entries (parameter kernel, default tidak diketahui?)

Kami tidak ingin memperburuk perutean Linux , jadi kami agak takut mengacaukan beberapa pengaturan ini.

Adakah yang bisa menyarankan parameter routing mana yang terbaik untuk disetel, untuk instance HAProxy lalu lintas tinggi?

Jeff Atwood
sumber

Jawaban:

28

Saya tidak pernah mengalami masalah ini. Namun, Anda mungkin harus meningkatkan lebar tabel hash Anda untuk mengurangi kedalamannya. Dengan menggunakan "dmesg", Anda akan melihat berapa banyak entri yang Anda miliki saat ini:

$ dmesg | grep '^IP route'
IP route cache hash table entries: 32768 (order: 5, 131072 bytes)

Anda dapat mengubah nilai ini dengan parameter baris perintah boot kernel rhash_entries. Pertama coba dengan tangan kemudian tambahkan ke lilo.confatau grub.conf.

Sebagai contoh: kernel vmlinux rhash_entries=131072

Ada kemungkinan bahwa Anda memiliki tabel hash yang sangat terbatas karena Anda telah menetapkan sedikit memori untuk HAProxy VM Anda (ukuran hash rute disesuaikan tergantung pada total RAM).

Mengenai tcp_mem, berhati-hatilah. Pengaturan awal Anda membuat saya berpikir Anda sedang menjalankan dengan 1 GB RAM, 1/3 di antaranya dapat dialokasikan ke soket TCP. Sekarang Anda telah mengalokasikan 367872 * 4096 byte = 1,5 GB RAM untuk soket TCP. Anda harus sangat berhati-hati untuk tidak kehabisan memori. Aturan praktisnya adalah untuk mengalokasikan 1/3 memori ke HAProxy dan 1/3 lainnya ke tumpukan TCP dan 1/3 terakhir ke seluruh sistem.

Saya menduga bahwa pesan "out of socket memory" Anda berasal dari pengaturan default di tcp_rmemdan tcp_wmem. Secara default, Anda memiliki 64 kB dialokasikan pada output untuk setiap soket dan 87 kB pada input. Ini berarti total 300 kB untuk koneksi proxy, hanya untuk buffer socket. Tambahkan ke 16 atau 32 kB untuk HAProxy, dan Anda melihat bahwa dengan 1 GB RAM Anda hanya akan mendukung 3000 koneksi.

Dengan mengubah pengaturan default tcp_rmemdan tcp_wmem(param tengah), Anda bisa mendapatkan memori yang lebih rendah. Saya mendapatkan hasil yang baik dengan nilai serendah 4096 untuk buffer tulis, dan 7300 atau 16060 dalam tcp_rmem(5 atau 11 segmen TCP). Anda dapat mengubah pengaturan tersebut tanpa memulai ulang, namun pengaturan itu hanya berlaku untuk koneksi baru.

Jika Anda memilih untuk tidak menyentuh Anda sysctls terlalu banyak, HAProxy terbaru, 1.4-dev8, memungkinkan Anda untuk men-tweak parameter tersebut dari konfigurasi global, dan per sisi (client atau server).

Saya berharap ini membantu!

Willy Tarreau
sumber
8

Ini Out of socket memory errorsering menyesatkan. Sebagian besar waktu, di server yang menghadapi Internet, tidak menunjukkan masalah terkait kehabisan memori. Seperti yang saya jelaskan dalam perincian yang jauh lebih besar dalam posting blog , alasan paling umum adalah jumlah soket anak yatim. Soket yatim adalah soket yang tidak terkait dengan deskriptor file. Dalam keadaan tertentu, kernel akan mengeluarkan Out of socket memory errormeskipun Anda 2x atau 4x jauh dari batas ( /proc/sys/net/ipv4/tcp_max_orphans). Ini sering terjadi di layanan yang menghadapi Internet dan sangat normal. Tindakan yang tepat dalam kasus ini adalah untuk menyetel tcp_max_orphanssetidaknya 4 kali lipat jumlah anak yatim yang biasanya Anda lihat dengan lalu lintas puncak Anda.

Jangan mendengarkan saran yang merekomendasikan penyetelan tcp_mematau tcp_rmematau tcp_wmemkecuali Anda benar - benar tahu apa yang Anda lakukan. Mereka yang memberikan saran ini biasanya tidak. Voodoo mereka sering salah atau tidak pantas untuk lingkungan Anda dan tidak akan menyelesaikan masalah Anda. Bahkan mungkin membuatnya lebih buruk.

tsuna
sumber
1
Ketika ini terjadi, pesannya berbeda di dmesg, Anda melihat "terlalu banyak soket yatim piatu". Namun saya setuju dengan Anda bahwa anak yatim dapat menghabiskan banyak memori.
Willy Tarreau
Ketika Anda melebihi jumlah /proc/sys/net/ipv4/tcp_max_orphansAnda akan mengalami kesalahan yang berbeda. Seluruh tumpukan Stack Exchange misalnya memiliki /proc/sys/net/ipv4/tcp_max_orphans65536 dan /proc/net/sockstatmenghasilkan TCP: inuse 2996 yatim 171 tw 15972 mengalokasikan 2998 mem 1621 - perbedaan yang tidak dapat diabaikan.
Geoff Dalgas
-4

Kami menyetel beberapa parameter ini secara teratur. Standar kami untuk throughput tinggi, platform perdagangan latensi rendah adalah:

net.ipv4.tcp_rmem = 4096 16777216 33554432
net.ipv4.tcp_wmem = 4096 16777216 33554432
net.ipv4.tcp_mem = 4096 16777216 33554432
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 30000
net.core.netdev_max_backlog = 30000
Scott Alan Miller
sumber
1
per Willy matematika itu berarti tekanan memori # standar Anda (nomor tengah) adalah 68 GB ?! Kali ketiga (rmem, wmem, mem) ??
Jeff Atwood
10
Tunable ini salah dan sangat sering ditemukan di lingkungan bangku kemudian disalin secara acak. Mereka tidak akan memiliki masalah dengan hanya beberapa sesi bersamaan, tetapi bahkan dengan 100 soket TCP, Anda akan mengalokasikan 3,2 GB RAM. Selama latensi rendah, Anda tidak akan melihat ada yang dicurigai. Anda hanya perlu mencabut mesin jarak jauh selama transfer untuk melihat buffer output terisi, atau membekukan tugas lokal dan melihat pengisian buffer input. Ini gila ...
Willy Tarreau
6
Jeff, ini bukan kali tiga. tcp_mem ada di halaman dan menentukan ukuran global. tcp_rmem dan tcp_wmem dalam byte dan menentukan ukuran per-socket.
Willy Tarreau
Lagu-lagu itu terlihat salah, untuk server bersamaan dengan data kecil Anda tidak ingin memesan buffer socket begitu banyak dan tcp_mem benar-benar berbeda dari r / wmem, menggunakan angka yang sama tidak masuk akal, (satu byte per koneksi yang lain halaman per sistem)
eckes