Apa metode khas untuk meningkatkan penyeimbang beban perangkat lunak?


22

Saya sering melihat arsitektur aplikasi web dengan SLB / reverse-proxy di depan sekelompok server aplikasi.

Apa yang terjadi ketika jumlah koneksi ke SLB membutuhkan terlalu banyak sumber daya untuk ditangani oleh satu SLB secara efektif? Untuk contoh konkret namun over-the-top, pertimbangkan 2 juta koneksi HTTP persisten. Jelas satu SLB tidak bisa menangani ini.

Apa konfigurasi direkomendasikan untuk skala keluar sebuah SLB?

Apakah itu khas untuk membuat grup / kluster LB? Jika demikian, bagaimana beban klien tersebar di antara kelompok LB?


z8000, Dapatkah Anda mengatakan penyeimbang beban perangkat lunak apa yang Anda gunakan? Juga, jika mungkin algoritma / protokol apa yang digunakannya untuk load-balancing.
Martin

Saya tidak punya preferensi. Saya memperbarui pertanyaan agar lebih jelas.
z8000

Tidak jelas bagi saya mengapa penyeimbang beban secara intrinsik tidak dapat menangani 2 juta koneksi HTTP persisten.
womble

Jawaban:


10

Load balancers tidak dapat dengan mudah diskalakan oleh balancers beban lainnya karena akan secara inheren ada penyeimbang beban tunggal pada rantai di suatu tempat yang menjaga koneksi. Yang mengatakan, penyeimbang seperti LVS atau HAProxy memiliki kapasitas tidak masuk akal dalam kisaran Gbps. Setelah Anda melampaui kemampuan penyeimbang beban tunggal (perangkat lunak, perangkat keras, apa pun), maka Anda harus beralih ke teknik lain seperti DNS round robin.


Kanan! Memiliki LB tunggal adalah "masalahnya". Saya setuju bahwa throughput tidak akan menjadi masalah secara umum. Tapi saya khawatir tentang sumber daya lain seperti RAM, yang dalam kasus saya terbatas. Hanya ada begitu banyak koneksi yang dapat di-host pada satu SLB sebelum RAM habis.
z8000

HAProxy dapat menangani sekitar 20k-60k sesi aktif per GB RAM. Saya percaya LVS dapat melakukan lebih banyak lagi, karena data sesi yang disimpan lebih kecil. Jika Anda kehabisan RAM, perbarui atau bangun penyeimbang beban lain yang digawangi oleh sistem DNS round-robin.
Hyppy

1
"Load balancers tidak dapat dengan mudah diskalakan oleh balancers beban lainnya" - sebenarnya, penyeimbang beban L4 berbasis ASIC sering kali dapat ditempatkan di depan beberapa penyeimbang beban berbasis L7 HTTP dengan hasil yang sangat baik. Prinsip dasar yang sama berlaku untuk implementasi perangkat lunak saja, misalnya Linux LVS di depan nignx.
Jesper M

19

OK, sudah ada jawaban yang diterima, tetapi ada sesuatu untuk ditambahkan .. Cara 'klasik' yang paling umum untuk menskalakan tingkat penyeimbang beban adalah (tanpa urutan tertentu):

  • DNS Round Robin untuk mempublikasikan beberapa alamat IP untuk domain tersebut. Untuk setiap alamat IP, terapkan pasangan server yang sangat tersedia (2 server bekerja sama untuk menjaga agar satu alamat IP berfungsi setiap saat.) Setiap IP sesuai dengan satu cluster penyeimbang beban, baik menggunakan peralatan atau server dengan perangkat lunak penyeimbangan beban. Skala secara horizontal dengan menambahkan lebih banyak pasangan penyeimbang beban sesuai kebutuhan.

  • Routing atau firewall tweak untuk menyebarkan beban ke banyak penyeimbang beban. Mintalah router depan atau firewall depan menyebarkan koneksi yang masuk ke beberapa alamat IP (masing-masing mewakili satu pasangan penyeimbang beban) dengan mem-hashing alamat IP sumber , memiliki beberapa rute dengan biaya yang sama ke load balancers, atau serupa.

  • Lapisan penyeimbang beban tingkat IP di depan lapisan penyeimbang beban tingkat HTTP . Penyeimbangan beban lapisan IP dapat diimplementasikan dalam ASIC / silikon, dan dapat digunakan dengan cepat untuk beberapa hal. Dengan demikian satu pasangan penyeimbang beban IP sering dapat 'mengikuti' dengan beberapa penyeimbang beban tingkat HTTP / HTTPS, dan memberikan tingkat kinerja multi-gigabit sambil menjaga arsitektur tetap bagus dan sederhana.

Akan sangat mendalam tentang berbagai cara melakukan hal di atas akan membutuhkan jawaban yang sangat panjang. Tetapi secara umum, tidak terlalu sulit untuk mengukur tingkat penyeimbang beban , jauh lebih sulit untuk mengukur tingkat server aplikasi dan terutama tingkat basis data.

Apakah Anda memilih faktor bentuk alat (F5, Cisco, A10) atau server generik (perangkat lunak Windows / Linux +) kurang penting. Pertimbangan utama saat menskalakan lapisan penyeimbang beban adalah:

  • State-full versus stateless. Apakah Anda benar-benar membutuhkan sesi yang lengket, atau dapatkah Anda hidup tanpanya? Tidak menjaga status membuat segalanya lebih sederhana.
  • 'Perangkat Keras' (ASIC) versus 'perangkat lunak' (server serba guna) untuk penyeimbangan beban. Masing-masing memiliki kelebihan dan kekurangannya, lihat dokumentasi ikhtisar HAProxy yang ditautkan di atas.
  • Load balancing L3 / 4 (IP / TCP / IP) versus load balancing L7 (HTTP) . Sekali lagi, pro dan kontra, dokumen HAProxy memberikan tinjauan yang baik.
  • Pengakhiran SSL , di mana, di webnodes atau di load balancer.

Secara umum, Anda tidak perlu khawatir tentang ini sebelum situs web Anda menjadi sangat besar - satu server modern dengan fx nginx akan menangani puluhan ribu permintaan HTTP sederhana per detik. Jadi jangan lakukan optimasi prematur, jangan berurusan dengan ini sebelum Anda harus.


Anda sebenarnya tidak perlu setiap alamat IP tersedia dengan menggunakan DNS RR. Browser, secara umum, akan kembali ke IP lain jika tersedia ketika mereka tidak dapat terhubung. Tetapi jika Anda memiliki layanan web publik, Anda akan memerlukan HA untuk setiap alamat IP, karena banyak perpustakaan layanan web tidak akan menangani kegagalan-ke IP lain secara otomatis.
rmalayter

9

Kunci untuk menskalakan lapisan penyeimbang beban HTTP adalah dengan menambahkan lapisan penyeimbangan beban level rendah (IP atau TCP) lainnya terlebih dahulu. Lapisan ini dapat dibangun sepenuhnya dengan perangkat lunak sumber terbuka, meskipun Anda akan mendapatkan hasil yang lebih baik jika Anda memiliki perute modern.

Aliran (sesi TCP) harus di hash menggunakan header seperti IP sumber / tujuan dan port TCP, untuk memutuskan frontend yang dituju. Anda juga membutuhkan mekanisme untuk memastikan bahwa ketika sebuah frontend mati, ia akan berhenti digunakan.

Ada berbagai strategi, saya akan menguraikan pasangan yang telah saya gunakan dalam produksi di situs yang melayani jutaan pengguna, sehingga Anda bisa mendapatkan idenya. Akan terlalu lama untuk menjelaskan semuanya secara terperinci tetapi saya harap jawaban ini akan memberi Anda cukup informasi / petunjuk untuk memulai. Untuk menerapkan solusi ini, Anda akan membutuhkan seseorang yang benar-benar berpengetahuan tentang jaringan.

Memang apa yang saya jelaskan di sini jauh lebih sulit diimplementasikan daripada apa yang dijelaskan dalam jawaban lain, tetapi ini benar-benar canggih jika Anda memiliki situs web yang diperdagangkan tinggi dengan masalah skalabilitas besar dan persyaratan ketersediaan lebih dari 99,9% . Asalkan Anda sudah memiliki insinyur jaringan yang lebih baik, ongkosnya lebih murah untuk pemasangan dan pengaturan (baik dalam capex dan opex) daripada peralatan penyeimbang beban, dan dapat ditingkatkan lebih lanjut dengan hampir tanpa biaya tambahan (vs. membeli yang baru, bahkan lebih alat mahal ketika Anda melebihi model Anda saat ini).

Strategi pertama: dengan firewall

Mungkin Anda memiliki beberapa router yang terhubung dengan ISP uplink Anda. ISP Anda menyediakan 2 tautan (aktif / pasif, menggunakan VRRP). Di router Anda, Anda juga menggunakan VRRP, dan Anda merutekan lalu lintas yang menuju jaringan publik Anda ke firewall. Firewall ( FW 1dan di FW 2bawah) juga aktif / pasif dan akan menyaring lalu lintas dan mengirim setiap aliran ke server frontend yang sehat (penyeimbang beban HTTP Anda, FE 1dan di FE 2bawah).

      + -------------- + + -------------- +
      | Router ISP A | | Router ISP B |
      + -------------- + + -------------- +
             | |
           == # ====================== # == (jaringan publik)
             | |
      + --------------- + + --------------- +
      | Router Anda A | | Router Anda B |
      + --------------- + + --------------- +
             | |
           == # ===== # ========== # ===== # == (jaringan pribadi RFC 1918)
             | | | |
       + ------ + + ------ + + ------ + + ------ +
       | FW 1 | | FE 1 | | FE 2 | | FW 2 |
       + ------ + + ------ + + ------ + + ------ +

Tujuannya agar tampilan menjadi seperti ini:

  1. ISP merutekan lalu lintas ke IP Anda ke router aktif Anda.
  2. Router Anda merutekan traffic ke VIP yang menggunakan alamat RFC 1918 . VIP ini dimiliki oleh firewall aktif, mirip seperti VRRP. Jika Anda menggunakan OpenBSD untuk kebutuhan firewall Anda, maka Anda dapat menggunakan CARP , alternatif bebas paten untuk VRRP / HSRP.
  3. Firewall Anda menerapkan filter (misalnya "hanya izinkan 80 / tcp dan 443 / tcp pergi ke alamat IP khusus ini").
  4. Firewall Anda juga bertindak sebagai router dan meneruskan paket ke frontend yang sehat.
  5. Frontend Anda mengakhiri koneksi TCP.

Sekarang keajaiban terjadi di langkah 4 dan 5, jadi mari kita lihat lebih detail apa yang mereka lakukan.

Firewall Anda mengetahui daftar frontend ( FE 1dan FE 2), dan ia akan memilih salah satu dari mereka berdasarkan aspek aliran tertentu (misalnya dengan hashing IP sumber dan port, di antara header lainnya). Tetapi juga perlu memastikan bahwa itu meneruskan lalu lintas ke frontend yang sehat, jika tidak Anda akan blackhole lalu lintas. Jika Anda menggunakan OpenBSD, misalnya, Anda dapat menggunakan relayd. Aparelaydmemang sederhana: memeriksa kesehatan semua frontend Anda (misalnya dengan mengirimkan mereka permintaan HTTP probe), dan setiap kali frontend sehat, ia menambahkannya ke tabel yang digunakan firewall untuk memilih paket paket berikutnya dari aliran yang diberikan . Jika frontend gagal pemeriksaan kesehatan, itu dihapus dari tabel dan tidak ada paket yang dikirim lagi. Saat meneruskan paket ke frontend, yang dilakukan firewall hanyalah menukar alamat tujuan MAC paket tersebut dengan yang ada di frontend yang dipilih.

Pada langkah 5, paket dari pengguna diterima oleh penyeimbang beban Anda (baik itu Varnish, nginx, atau apa pun). Pada titik ini, paket tersebut masih diperuntukkan bagi alamat IP publik Anda sehingga Anda perlu menambahkan VIP pada antarmuka loopback. Ini disebut DSR (Direct Server Return), karena frontend Anda mengakhiri koneksi TCP dan firewall di antara hanya melihat lalu lintas simpleks (hanya paket yang masuk). Router Anda akan merutekan paket keluar langsung kembali ke router ISP. Ini sangat baik untuk lalu lintas HTTP karena permintaan cenderung lebih kecil dari respons, kadang-kadang secara signifikan. Untuk lebih jelasnya: ini bukan hal khusus OpenBSD dan banyak digunakan di situs web yang diperdagangkan tinggi.

Gotchas:

  • Pengguna akhir akan langsung terhubung ke server frontend Anda karena Anda menggunakan DSR. Mungkin memang sudah demikian, tetapi jika tidak, Anda harus memastikan semuanya sudah diamankan.
  • Jika Anda menggunakan OpenBSD, berhati-hatilah karena kernel berulir tunggal sehingga kinerja inti CPU tunggal akan membatasi throughput firewall. Ini mungkin masalah tergantung pada jenis NIC Anda dan tingkat paket yang Anda lihat. Ada cara untuk mengatasi masalah ini (lebih lanjut tentang ini di bawah).

Strategi kedua: tanpa firewall

Strategi ini lebih efisien tetapi lebih sulit untuk diatur karena lebih tergantung pada spesifikasi router yang Anda miliki. Idenya adalah untuk mem-bypass firewall di atas dan membuat router melakukan semua pekerjaan yang dilakukan firewall.

Anda akan memerlukan router yang mendukung per-port L3 / L4 ACL, BGP dan ECMP , dan Policy Based Routing (PBR). Hanya router kelas atas yang mendukung fitur-fitur ini, dan mereka seringkali memiliki biaya lisensi tambahan untuk menggunakan BGP. Ini biasanya masih lebih murah daripada penyeimbang beban perangkat keras, dan juga jauh lebih mudah untuk diukur. Hal yang baik tentang router kelas atas ini adalah bahwa mereka cenderung menjadi line-rate (misalnya mereka selalu dapat memaksimalkan tautan, bahkan pada antarmuka 10GbE, karena semua keputusan yang mereka buat dilakukan dalam perangkat keras oleh ASIC).

Pada port yang memiliki ISP uplink Anda, terapkan ACL yang dulu ada di firewall (mis. "Hanya izinkan 80 / tcp dan 443 / tcp pergi ke alamat IP khusus ini"). Kemudian mintalah masing-masing frontend Anda mempertahankan sesi BGP dengan router Anda. Anda dapat menggunakan OpenBGPD yang sangat baik (jika frontend Anda menggunakan OpenBSD) atau Quagga . Router Anda akan ECMP lalu lintas ke frontend yang sehat (karena mereka mempertahankan sesi BGP mereka). Router juga akan merutekan traffic keluar dengan menggunakan PBR.

Perbaikan

  • Dengan solusi pasangan firewall, alangkah baiknya jika Anda dapat menyinkronkan status TCP di seluruh firewall, sehingga ketika satu firewall gagal, semuanya gagal dengan lancar ke yang lainnya. Anda dapat mencapai ini dengan pfsync.
    • Ingatlah bahwa pfsyncbiasanya akan menggandakan laju paket pada firewall Anda.
    • HTTP adalah protokol tanpa kewarganegaraan, jadi ini bukan akhir dunia jika Anda mengatur ulang semua koneksi selama firewall gagal karena Anda tidak menggunakannya pfsync.
  • Jika Anda melebihi firewall tunggal, Anda dapat menggunakan ECMP pada router Anda untuk merutekan lalu lintas ke lebih dari satu pasang firewall.
  • Jika Anda menggunakan lebih dari satu pasang firewall, Anda mungkin membuatnya semuanya aktif / aktif. Anda dapat mencapai ini dengan meminta firewall mempertahankan sesi BGP dengan router, seperti halnya frontend perlu mempertahankannya dalam desain ke-2 tanpa firewall.

Contoh relaydkonfigurasi

Lihat juga HOWTO di https://calomel.org/relayd.html

vip = "1.2.3.4" # Alamat IP publik Anda
               # (Anda dapat memiliki lebih dari satu, tetapi tidak perlu)
fe1 = "10.1.2.101"
fe2 = "10.1.2.102"
fe3 = "10.1.2.103"
fe4 = "10.1.2.104" # Anda dapat memiliki sejumlah frontend.
int_if = "em0"
tabel <fe> {$ fe1 coba lagi 2, $ fe2 coba lagi 2, $ fe3 coba lagi 2, $ fe4 coba lagi 2}
tabel <fallback> {127.0.0.1}

redirect webtraffic {
        dengarkan pada $ vip port 80
        batas waktu sesi 60
        rute ke <fe> periksa http "/healthcheck.html" digest "(sha1sum of healthcheck.html)" interface $ int_if
}

2

Secara pribadi saya pergi ke penyeimbang beban perangkat keras yang lebih sederhana dan tidak dapat dikonfigurasi pada saat itu - hal-hal seperti ACE / ASAs Cisco, Foundry ServerIron, bahkan mungkin Zeus ZXTMs (LB SW yang dirancang untuk beban yang sangat berat).


Dengan kata lain skala up ? LB semacam itu masih akan maksimal di sejumlah koneksi (dll.). Lalu bagaimana? Itu benar-benar pertanyaan saya. Terima kasih!
z8000

1
Benar-benar situs besar hanya menggunakan banyak tugas berat yang dijalankan LB di bawah semacam DNS round-robin - cukup bagus untuk saat ini bagi sebagian besar dan dapat menangani ratusan juta koneksi. Yang mengatakan ada pertanyaan mengapa begitu banyak koneksi harus tetap terbuka tentu saja ...
Chopper3

Apakah itu maksud Anda RRDNS internal ? Rapi, saya tidak memikirkan itu. Re: buka koneksi ... Saya sedang menjajaki opsi untuk aplikasi yang membutuhkan pengiriman pembaruan ke klien yang terhubung dari waktu ke waktu karena peristiwa terjadi di suatu tempat di backend. Saya terpecah antara server TCP khusus atau banyak koneksi HTTP terbuka di belakang SLB. Terima kasih atas komentar anda
z8000

Saya akan berpikir itu harus RRDNS eksternal. Misalnya, Twitter.com akan menggunakan RRDNS untuk menyelesaikan & mendistribusikan permintaan ke salah satu dari banyak LB besar yang kemudian akan mendistribusikan beban ke server.
Robert

Ya Robert, Anda benar, misalnya kami menggunakan kotak Cisco GSS untuk melakukan situs demi situs RR.
Chopper3

1

Mungkin alih-alih terus-menerus menjaga begitu banyak koneksi terbuka untuk mengirim balasan, beri kode aplikasi Anda sedemikian rupa sehingga klien akan secara berkala menyurvei server Anda sesering yang diperlukan?

Apakah apa pun yang Anda lakukan sebenarnya memerlukan respons milidetik ini atau bisakah klien menunggu 15/20 detik hingga periode pemungutan suara berikutnya?


0

Pendekatan tipikal adalah membuat cluster yang cukup besar untuk menangani beban yang diperlukan dan menggunakan SLB yang dapat melakukan load-balancing deterministik (untuk kasus koneksi persisten).

Sesuatu seperti CARP menggunakan hash IP yang meminta untuk menentukan server web backend mana yang akan menangani permintaan, ini harus bersifat deterministik tetapi tidak terlalu berguna jika ada firewall atau NAT di depan load balancer Anda.
Anda juga dapat menemukan sesuatu seperti IPVS yang berguna jika Anda menjalankan Linux.


Apa yang Anda klaim tentang ikan mas sangat jauh dari cara kerjanya, saya tidak akan tahu harus mulai dari mana! + -0 untuk menyebutkan IPVS.
3

@ 3molo ... ya? lihat net.inet.carp.arpbalance di linux.com/archive/feed/35482 "..CARP source-hashes IP asal permintaan. hash kemudian digunakan untuk memilih virtual host dari pool yang tersedia untuk menangani permintaan tersebut . "
Paul
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.