Saya menjalankan server penyeimbang beban HAProxy untuk menyeimbangkan beban ke beberapa server Apache. Saya perlu memuat ulang HAProxy kapan saja untuk mengubah algoritma load balancing.
Ini semua berfungsi dengan baik, kecuali kenyataan bahwa saya harus memuat ulang server tanpa kehilangan satu paket (saat ini memuat ulang rata-rata memberi saya 99,76% keberhasilan rata-rata, dengan 1000 permintaan per detik selama 5 detik). Saya telah melakukan banyak penelitian tentang hal ini, dan telah menemukan perintah berikut untuk "memuat ulang secara anggun" server HAProxy:
haproxy -D -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)
Namun, ini memiliki sedikit atau tidak ada efek versus yang lama service haproxy reload
, itu masih turun rata-rata 0,24%.
Apakah ada cara untuk memuat ulang file konfigurasi HAProxy tanpa satu paket pun yang dijatuhkan dari pengguna mana pun?
Jawaban:
Menurut https://github.com/aws/opsworks-cookbooks/pull/40 dan akibatnya http://www.mail-archive.com/[email protected]/msg06885.html Anda dapat:
sumber
iptables v1.4.14: invalid port/service
--syn 'ditentukan`$PORT
dengan port yang sebenarnyahaproxy
sedang mendengarkan. Jika haproxy mendengarkan pada banyak port, tulis ganti--dport $PORT
dengan--dports $PORTS_SEPARATED_BY_COMMAS
, misalnya--dports 80,443
,.Yelp berbagi pendekatan yang lebih canggih berdasarkan pengujian yang cermat. Artikel blog adalah menyelam dalam, dan layak investasi waktu untuk sepenuhnya menghargainya.
True Zero Downtime HAProxy Reloads
tl; dr menggunakan Linux tc (traffic control) dan iptables untuk sementara mengantri paket SYN sementara HAProxy sedang memuat ulang dan memiliki dua pids yang terpasang pada port yang sama (
SO_REUSEPORT
).Saya tidak nyaman menerbitkan kembali seluruh artikel di ServerFault; namun demikian, berikut adalah beberapa kutipan untuk menyinggung minat Anda:
Intisari: https://gist.github.com/jolynch/97e3505a1e92e35de2c0
Bersorak untuk Yelp karena berbagi wawasan yang luar biasa.
sumber
Ada cara lain yang jauh lebih sederhana untuk memuat ulang haproxy dengan benar-benar downtime - dinamakan iptables flipping (artikelnya sebenarnya adalah Unbounce response to Yelp solution). Ini lebih bersih daripada jawaban yang diterima karena tidak perlu menjatuhkan paket yang dapat menyebabkan masalah dengan isi ulang yang lama.
Secara singkat, solusinya terdiri dari langkah-langkah berikut:
iptable
perintah sederhana .Selain itu, solusinya dapat diadopsi untuk semua jenis layanan (nginx, apache dll) dan lebih toleran terhadap kesalahan karena Anda dapat menguji konfigurasi siaga sebelum online.
sumber
Sunting: Jawaban saya membuat asumsi bahwa kernel hanya mengirimkan lalu lintas ke port terbaru untuk dibuka dengan SO_REUSEPORT, padahal sebenarnya mengirimkan lalu lintas ke semua proses seperti yang dijelaskan dalam salah satu komentar. Dengan kata lain, tarian iptables masih diperlukan. :(
Jika Anda menggunakan kernel yang mendukung SO_REUSEPORT, maka masalah ini seharusnya tidak terjadi.
Proses yang haproxy lakukan saat restart adalah:
1) Coba atur SO_REUSEPORT saat membuka port ( https://github.com/haproxy/haproxy/blob/3cd0ae963e958d5d5fb838e120f1b0e9361a92f8/src/proto_tcp.c#L792-L798 )
2) Coba buka port (akan berhasil dengan SO_REUSEPORT)
3) Jika tidak berhasil, beri tanda proses lama untuk menutup port-nya, tunggu 10 ms dan coba semuanya lagi. ( https://github.com/haproxy/haproxy/blob/3cd0ae963e958d5d5fb838e120f1b0e9361a92f8/src/haproxy.c#L1554-L1577 )
Pertama kali didukung di kernel Linux 3.9 tetapi beberapa distro telah mendukungnya. Sebagai contoh, kernel EL6 dari 2.6.32-417.el6 mendukungnya.
sumber
SO_REUSEPORT
beberapa skenario tertentu - terutama di bawah lalu lintas padat. Ketika SYN dikirim ke proses haproxy lama dan pada saat yang sama ia menutup soket pendengaran yang menghasilkan RST. Lihat artikel Yelp yang disebutkan dalam jawaban lain di atas.Saya akan menjelaskan pengaturan saya dan bagaimana saya memecahkan ulang yang anggun:
Saya memiliki pengaturan khas dengan 2 node yang menjalankan HAproxy dan terus dihidupkan. Keepalived melacak antarmuka dummy0, jadi saya bisa melakukan "ifconfig dummy0 down" untuk memaksa beralih.
Masalah sebenarnya adalah bahwa, saya tidak tahu mengapa, "haproxy reload" masih menjatuhkan semua koneksi ESTABLISHED :( Saya mencoba "iptables flipping" yang diajukan oleh gertas, tapi saya menemukan beberapa masalah karena melakukan NAT pada tujuan. Alamat IP, yang bukan solusi yang cocok dalam beberapa skenario.
Sebagai gantinya, saya memutuskan untuk menggunakan hack kotor CONNMARK untuk menandai paket-paket milik koneksi BARU, dan kemudian mengarahkan paket-paket yang ditandai ke node lain.
Berikut adalah aturan dasar iptables:
Dua aturan pertama menandai paket-paket milik arus baru (123.123.123.123 adalah VIP yang disimpan tetap yang digunakan pada haproxy untuk mengikat frontend).
Paket tanda aturan ketiga dan keempat paket FIN / RST. (Saya tidak tahu mengapa, TEE menargetkan "mengabaikan" paket FIN / RST).
Aturan kelima mengirim duplikat dari semua paket yang ditandai ke HAproxy lainnya (192.168.0.2).
Aturan keenam menjatuhkan paket milik arus baru untuk mencegah mencapai tujuan awal mereka.
Ingatlah untuk menonaktifkan rp_filter pada antarmuka atau kernel akan menjatuhkan paket-paket martian itu.
Dan last but not least, keberatan paket kembali! Dalam kasus saya ada perutean asimetris (permintaan datang ke klien -> haproxy1 -> haproxy2 -> webserver, dan balasan pergi dari server web -> haproxy1 -> client), tetapi tidak mempengaruhi. Ini bekerja dengan baik.
Saya tahu solusi paling elegan adalah dengan menggunakan iproute2 untuk melakukan pengalihan, tetapi hanya bekerja untuk paket SYN pertama. Ketika menerima ACK (paket ke-3 dari jabat tangan 3 arah), itu tidak menandainya :( Saya tidak bisa menghabiskan banyak waktu untuk menyelidiki, begitu saya melihatnya bekerja dengan target TEE, ia meninggalkannya di sana. Tentu saja, silakan mencobanya dengan iproute2.
Pada dasarnya, "reload anggun" berfungsi seperti ini:
Aturan IPtables dapat dengan mudah diintegrasikan ke dalam skrip start / stop:
sumber