http tetap hidup di zaman modern

92

Jadi menurut penulis haproxy, siapa yang tahu satu atau dua hal tentang http:

Keep-hidup diciptakan untuk mengurangi penggunaan CPU di server saat CPU 100 kali lebih lambat. Tapi yang tidak dikatakan adalah bahwa koneksi persisten menghabiskan banyak memori sementara tidak dapat digunakan oleh siapa pun kecuali klien yang membukanya. Hari ini di tahun 2009, CPU sangat murah dan memori masih terbatas pada beberapa gigabyte berdasarkan arsitektur atau harganya. Jika situs perlu tetap hidup, ada masalah nyata. Situs dengan muatan tinggi sering kali menonaktifkan keep-hidup untuk mendukung klien simultan dalam jumlah maksimum. Kelemahan sebenarnya dari tidak memiliki keep-hidup adalah latensi yang sedikit meningkat untuk mengambil objek. Browser menggandakan jumlah koneksi bersamaan di situs non-keepalive untuk mengimbangi hal ini.

(dari http://haproxy.1wt.eu/ )

Apakah ini sejalan dengan pengalaman orang lain? yaitu tanpa keep-hidup - apakah hasilnya hampir tidak terlihat sekarang? (mungkin perlu dicatat bahwa dengan websockets dll - koneksi tetap "terbuka" terlepas dari status tetap hidup - untuk aplikasi yang sangat responsif). Apakah efeknya lebih besar untuk orang yang jauh dari server - atau jika ada banyak artefak untuk dimuat dari host yang sama saat memuat halaman? (Saya pikir hal-hal seperti CSS, gambar dan JS semakin banyak berasal dari CDN yang ramah cache).

Pikiran?

(tidak yakin apakah ini adalah masalah serverfault.com, tetapi saya tidak akan mengirim silang sampai seseorang menyuruh saya untuk memindahkannya ke sana).

Michael Neale
sumber
1
Perlu dicatat bahwa di bagian lain dokumentasi untuk haproxy yang keep-hidup disebutkan dalam istilah lain yang lebih menguntungkan. Saya ingin sekali mendengar tentang pengalaman orang-orang, terutama untuk hosting massal.
Michael Neale
"Dapatkan web / server aplikasi yang dirancang lebih baik"? :-) Desain yang lebih baru (seperti Jetty) dengan kelanjutan (-seperti) koneksi penanganan pada dasarnya mengurangi masalah memori / thread. Juga, "beberapa GB" terdengar seperti istilah server 2008/2009 ;-)
3
Kedengarannya seperti twaddle bagi saya. RTT tambahan yang terlibat dalam pengaturan soket baru adalah batas fisik yang keras yang seringkali cukup lama untuk dapat dideteksi oleh manusia dan tidak dapat dikurangi dalam hukum fisika yang diketahui. Sebaliknya, RAM semakin murah, semakin murah, dan tidak ada alasan untuk soket idle menggunakan lebih dari beberapa kB.
Akankah Dean
2
Tapi yang menarik adalah ini bukan hanya teori - ini adalah penulis haproxy. Semua yang saya dengar hanyalah teori dan asumsi.
Michael Neale

Jawaban:

141

Hai, karena saya penulis kutipan ini, saya akan menjawab :-)

Ada dua masalah besar di situs besar: koneksi bersamaan dan latensi. Koneksi serentak disebabkan oleh klien lambat yang membutuhkan waktu lama untuk mengunduh konten, dan oleh status koneksi tidak aktif. Status koneksi idle tersebut disebabkan oleh koneksi yang digunakan kembali untuk mengambil beberapa objek, yang dikenal sebagai keep-hidup, yang selanjutnya ditingkatkan oleh latensi. Ketika klien sangat dekat dengan server, klien dapat menggunakan koneksi secara intensif dan memastikannya hampir tidak pernah menganggur. Namun ketika urutannya berakhir, tidak ada yang peduli untuk menutup saluran dengan cepat dan koneksi tetap terbuka dan tidak digunakan untuk waktu yang lama. Itulah alasan mengapa banyak orang menyarankan untuk menggunakan waktu tunggu keep-hidup yang sangat rendah. Pada beberapa server seperti Apache, batas waktu terendah yang dapat Anda setel adalah satu detik, dan seringkali terlalu berlebihan untuk mempertahankan beban tinggi: jika Anda memiliki 20.000 klien di depan Anda dan mereka mengambil rata-rata satu objek setiap detik, Anda akan memiliki 20.000 koneksi yang dibuat secara permanen. 20.000 koneksi bersamaan pada server tujuan umum seperti Apache sangat besar, akan membutuhkan antara 32 dan 64 GB RAM tergantung pada modul apa yang dimuat, dan Anda mungkin tidak dapat berharap untuk meningkatkannya bahkan dengan menambahkan RAM. Dalam praktiknya, untuk 20.000 klien Anda bahkan dapat melihat 40.000 hingga 60.000 koneksi bersamaan di server karena browser akan mencoba menyiapkan 2 hingga 3 koneksi jika mereka memiliki banyak objek untuk diambil. dan Anda mungkin tidak bisa berharap lebih tinggi bahkan dengan menambahkan RAM. Dalam praktiknya, untuk 20.000 klien Anda bahkan dapat melihat 40.000 hingga 60.000 koneksi bersamaan di server karena browser akan mencoba menyiapkan 2 hingga 3 koneksi jika mereka memiliki banyak objek untuk diambil. dan Anda mungkin tidak bisa berharap lebih tinggi bahkan dengan menambahkan RAM. Dalam praktiknya, untuk 20.000 klien Anda bahkan dapat melihat 40.000 hingga 60.000 koneksi bersamaan di server karena browser akan mencoba menyiapkan 2 hingga 3 koneksi jika mereka memiliki banyak objek untuk diambil.

Jika Anda menutup koneksi setelah setiap objek, jumlah koneksi bersamaan akan menurun drastis. Memang, itu akan turun dengan faktor yang sesuai dengan waktu rata-rata untuk mengunduh objek pada waktu antar objek. Jika Anda memerlukan 50 md untuk mengunduh sebuah objek (foto miniatur, tombol, dll ...), dan Anda mengunduh rata-rata 1 objek per detik seperti di atas, maka Anda hanya akan memiliki 0,05 koneksi per klien, yaitu hanya 1000 koneksi bersamaan untuk 20.000 klien.

Sekarang waktu untuk membangun koneksi baru akan dihitung. Klien jarak jauh akan mengalami latensi yang tidak menyenangkan. Di masa lalu, browser menggunakan koneksi bersamaan dalam jumlah besar saat keep-living dinonaktifkan. Saya ingat angka 4 di MSIE dan 8 di Netscape. Ini benar-benar akan membagi rata-rata latensi per objek sebanyak itu. Sekarang keep-hidup hadir di mana-mana, kami tidak melihat angka yang tinggi itu lagi, karena melakukan hal itu semakin meningkatkan beban pada server jarak jauh, dan browser menjaga perlindungan infrastruktur Internet.

Ini berarti bahwa dengan browser saat ini, lebih sulit untuk mendapatkan layanan non-keep-hidup sebanyak yang responsif seperti yang keep-hidup. Juga, beberapa browser (misalnya: Opera) menggunakan heuristik untuk mencoba menggunakan pipelinining. Pipelining adalah cara yang efisien untuk menggunakan keep-hidup, karena hampir menghilangkan latensi dengan mengirimkan banyak permintaan tanpa menunggu respons. Saya sudah mencobanya di halaman dengan 100 foto kecil, dan akses pertama sekitar dua kali lebih cepat daripada tanpa keep-hidup, tetapi akses berikutnya sekitar 8 kali lebih cepat, karena responsnya sangat kecil sehingga hanya latensi yang dihitung (hanya "304").

Saya akan mengatakan bahwa idealnya kita harus memiliki beberapa tunable di browser untuk membuatnya menjaga koneksi tetap hidup antara objek yang diambil, dan segera menjatuhkannya ketika halaman selesai. Tapi sayangnya kami tidak melihatnya.

Untuk alasan ini, beberapa situs yang perlu menginstal server tujuan umum seperti Apache di bagian depan dan yang harus mendukung klien dalam jumlah besar biasanya harus menonaktifkan keep-living. Dan untuk memaksa browser meningkatkan jumlah koneksi, mereka menggunakan banyak nama domain sehingga unduhan dapat diparalelkan. Ini sangat bermasalah di situs yang menggunakan SSL secara intensif karena pengaturan koneksi bahkan lebih tinggi karena ada satu perjalanan pulang pergi tambahan.

Apa yang lebih umum diamati saat ini adalah bahwa situs tersebut lebih suka menginstal frontend ringan seperti haproxy atau nginx, yang tidak memiliki masalah menangani puluhan hingga ratusan ribu koneksi bersamaan, mereka mengaktifkan keep-hidup di sisi klien, dan menonaktifkannya di Sisi Apache. Di sisi ini, biaya membangun koneksi hampir nol dalam hal CPU, dan tidak terlihat sama sekali dalam hal waktu. Dengan begitu, ini memberikan yang terbaik dari kedua dunia: latensi rendah karena tetap hidup dengan waktu tunggu yang sangat rendah di sisi klien, dan jumlah koneksi yang rendah di sisi server. Semua orang bahagia :-)

Beberapa produk komersial lebih meningkatkannya dengan menggunakan kembali koneksi antara front load balancer dan server dan melakukan multiplexing pada semua koneksi klien di atasnya. Ketika server dekat dengan LB, keuntungannya tidak jauh lebih tinggi dari solusi sebelumnya, tetapi seringkali membutuhkan adaptasi pada aplikasi untuk memastikan tidak ada risiko penyeberangan sesi antar pengguna karena berbagi koneksi yang tidak terduga antara banyak pengguna . Secara teori, hal ini seharusnya tidak pernah terjadi. Kenyataannya jauh berbeda :-)

Willy Tarreau
sumber
1
Terima kasih atas jawaban yang lengkap dan lengkap! Saya sedikit bingung dengan berbagai komentar di halaman tentang keep-hidup - tapi ini semua masuk akal.
Michael Neale
Menariknya - Saya telah mengamati Chrome di linux menggunakan kembali koneksi yang tetap hidup selama beberapa detik - yaitu waktu yang dibutuhkan untuk membuka tab lain - tab lain ini adalah untuk nama host yang berbeda, tetapi diselesaikan melalui wildcard DNS ke server yang sama (massal virtual hosting) - dan dengan demikian menggunakan kembali koneksi yang sama! (ini membuat saya terkejut, bukan jenis yang baik - jelas jika tetap hidup hanya sisi klien, itu baik-baik saja).
Michael Neale
Yang saya dengar hanyalah "menggunakan apa pun selain apache dan itu bukan masalah besar". Apa yang saya perkirakan adalah "nonaktifkan mod_php dan penumpang dan bahkan apache mungkin memiliki kesempatan untuk bertarung".
coolaj86
@ CoolAJ86: intinya sama sekali bukan untuk menampar Apache, dan saya secara pribadi menggunakannya. Intinya adalah bahwa semakin umum server, semakin sedikit opsi yang harus Anda skalakan. Beberapa modul memerlukan model pre-fork maka Anda tidak dapat menskalakan koneksi dalam jumlah besar. Tetapi seperti yang dijelaskan itu bukan masalah besar karena Anda dapat menggabungkannya dengan komponen gratis lain seperti haproxy. Mengapa ada orang yang mengganti semuanya dalam kasus ini? Lebih baik instal haproxy daripada repot-repot menerapkan ulang aplikasi Anda menggunakan server lain!
Willy Tarreau
22

Pada tahun-tahun sejak ini ditulis (dan diposting di sini di stackoverflow) kami sekarang memiliki server seperti nginx yang semakin populer.

nginx misalnya dapat menyimpan 10.000 koneksi tetap hidup dalam satu proses dengan hanya 2,5 MB (megabyte) RAM. Nyatanya sangat mudah untuk membuka beberapa ribu koneksi dengan RAM yang sangat sedikit, dan satu-satunya batasan yang akan Anda capai adalah batasan lain seperti jumlah pegangan file yang terbuka atau koneksi TCP.

Keep-hidup adalah masalah bukan karena masalah dengan spesifikasi keep-hidup itu sendiri tetapi karena model skala berbasis proses Apache dan keep-alives diretas ke server yang arsitekturnya tidak dirancang untuk mengakomodasi itu.

Yang paling bermasalah adalah Apache Prefork + mod_php + keep-alives. Ini adalah model di mana setiap koneksi akan terus menempati semua RAM yang ditempati oleh proses PHP, bahkan jika itu benar-benar idle dan hanya tetap terbuka sebagai keep-hidup. Ini tidak dapat diskalakan. Tetapi server tidak harus dirancang seperti ini - tidak ada alasan khusus server perlu menyimpan setiap koneksi yang tetap hidup dalam proses terpisah (terutama tidak ketika setiap proses tersebut memiliki interpreter PHP lengkap). PHP-FPM dan model pemrosesan server berbasis event seperti yang di nginx memecahkan masalah dengan elegan.

Perbarui 2015:

SPDY dan HTTP / 2 menggantikan fungsionalitas keep-hidup HTTP dengan sesuatu yang lebih baik: kemampuan tidak hanya untuk menjaga koneksi tetap hidup dan membuat banyak permintaan dan tanggapan di atasnya, tetapi juga untuk multiplexing, sehingga tanggapan dapat dikirim dalam urutan apapun , dan secara paralel, bukan hanya dalam urutan permintaannya. Ini mencegah respons yang lambat memblokir respons yang lebih cepat dan menghilangkan godaan bagi browser untuk membuka beberapa koneksi paralel ke satu server. Teknologi ini lebih jauh menyoroti kekurangan dari pendekatan mod_php dan keuntungan dari sesuatu seperti server web berbasis event (atau paling tidak, multi-threaded) yang digabungkan secara terpisah dengan sesuatu seperti PHP-FPM.

thomasrutter
sumber
2

pemahaman saya adalah bahwa itu tidak ada hubungannya dengan CPU, tetapi latensi dalam pembukaan soket yang berulang ke sisi lain dunia. bahkan jika Anda memiliki lebar pita tak terbatas, latensi sambungan akan memperlambat keseluruhan proses. diperkuat jika halaman Anda memiliki lusinan objek. bahkan koneksi persisten memiliki latensi permintaan / respons tetapi berkurang ketika Anda memiliki 2 soket rata-rata, satu harus mengalirkan data sementara yang lain mungkin memblokir. Juga, router tidak akan pernah menganggap soket terhubung sebelum membiarkan Anda menulis ke sana. Ini membutuhkan jabat tangan pulang pergi penuh. sekali lagi, saya tidak mengaku sebagai seorang ahli, tapi begitulah saya selalu melihatnya. apa yang benar-benar keren adalah protokol ASYNC sepenuhnya (bukan, bukan protokol yang benar-benar sakit).

catchpolenet
sumber
ya - itu akan menjadi asumsi saya. mungkin ini adalah pertukaran - ada titik di mana latensi (karena jarak) berarti bahwa itu adalah masalah nyata
Michael Neale
ok, jadi tipografi modern akan membuat Anda terhubung ke proxy yang dekat (mungkin). tetapi kemudian apakah Anda memperluas pertanyaan ke apakah proxy harus menggunakan koneksi persisten?
catchpolenet
@Michael Neale juga, karena hal-hal seperti mulai lambat TCP, penalti latensi sebenarnya jauh lebih buruk daripada yang Anda perkirakan.
MartinodF
mungkin trade off adalah periode batas waktu yang jauh lebih singkat. jika Anda memiliki permintaan yang dicadangkan, mengapa mematikan soket dan memulai lagi? bahkan 1 detik akan memungkinkan halaman dimuat dengan ketekunan penuh dan kemudian menutup soket segera setelahnya.
catchpolenet
2

Keep-alives yang sangat panjang dapat berguna jika Anda menggunakan CDN "origin pull" seperti CloudFront atau CloudFlare. Faktanya, ini bisa bekerja lebih cepat daripada tanpa CDN, meskipun Anda menyajikan konten yang sepenuhnya dinamis.

Jika Anda sudah lama menyimpan data aktif sehingga setiap PoP pada dasarnya memiliki koneksi permanen ke server Anda, maka saat pengguna pertama kali mengunjungi situs Anda, mereka dapat melakukan jabat tangan TCP cepat dengan PoP lokal mereka alih-alih jabat tangan lambat dengan Anda. (Light itu sendiri membutuhkan waktu sekitar 100ms untuk pergi setengah jalan di seluruh dunia melalui fiber, dan membuat koneksi TCP membutuhkan tiga paket untuk diteruskan bolak-balik. SSL membutuhkan tiga perjalanan bolak-balik .)

mjs
sumber
1
Saya tergoda untuk memberi +1, tetapi paragraf kedua Anda memiliki komentar yang salah tentang cahaya yang hanya membutuhkan 10 md untuk melakukan perjalanan setengah jalan di seluruh dunia. Kecepatan cahaya 10 ms dalam vakum adalah 3000 km dan 10 ms kecepatan cahaya dalam serat tidak lebih dari 2000 km; setengah jalan di seluruh dunia (di sepanjang permukaan) adalah 20.000 km. Jadi itu akan menjadi 100 md - seandainya serat Anda langsung dari London ke Sydney daripada mengelilingi Afrika melalui laut atau mengambil rute panjang melalui Hawaii ...
piramida
@pyramids Anda benar, entah saya salah ketik, atau hanya main-main. Akan memperbarui.
mjs