Mengapa server web asinkron muncul?

Halo semuanya. Dalam sentuhan Vladislav Rodin. Saat ini, saya adalah kepala kursus Arsitek Beban Tinggi di OTUS, dan saya juga mengajar kursus arsitektur perangkat lunak.

Selain mengajar, seperti yang Anda lihat, saya telah menulis untuk materi hak cipta blog OTUS Habré dan artikel hari ini saya ingin bertepatan dengan dimulainya kursus «Linux Administrator" , yang sekarang sedang membuka set.





pengantar


Mengapa aplikasi web melambat dan tidak menahan beban? Para pengembang, yang pertama kali menghadapi pertanyaan seperti itu dan melakukan penelitian pada beberapa sistem, sampai pada kesimpulan yang mengecewakan bahwa mengoptimalkan logika bisnis saja tidak akan cukup. Jawaban atas pertanyaan ini terletak pada level yang lebih rendah - pada level sistem operasi. Agar aplikasi Anda dapat menahan beban, perlu untuk merevisi konsep arsitekturnya sedemikian rupa sehingga berfungsi secara efektif pada level ini. Hal ini menyebabkan munculnya server web yang tidak sinkron.

Sayangnya, saya tidak dapat menemukan satu bahan pun yang memungkinkan saya mengembalikan semua hubungan sebab akibat dalam evolusi server web sekaligus. Jadi ide untuk menulis artikel ini muncul, yang, saya harap, akan menjadi bahan seperti itu.

Fitur OS Linux


Sebelum berbicara tentang model server web, saya membiarkan diri saya mengingat beberapa fitur dari proses dan utas di Linux. Kita akan membutuhkan ini ketika menganalisis kelebihan dan kekurangan dari model di atas.

Sakelar konteks


Kemungkinan besar, setiap pengguna yang tahu bahwa hanya satu program dapat dijalankan pada satu inti prosesor sekaligus akan bertanya: "Mengapa 20 program dapat diluncurkan pada prosesor 4-inti saya sekaligus?".

Faktanya, ini disebabkan oleh fakta bahwa preemptive multitasking terjadi . Sistem operasi mengalokasikan kuantum waktu tertentu (~ 50 μs) dan menempatkan program untuk dieksekusi pada kernel selama waktu ini. Setelah waktu habis, saklar konteks terputus dan diaktifkan. Artinya, sistem operasi hanya menempatkan program berikutnya untuk dijalankan. Karena pergantian sering terjadi, kami mendapat kesan bahwa semua program bekerja secara bersamaan. Perhatikan frekuensi switching yang tinggi, ini akan menjadi penting untuk presentasi selanjutnya.

Switch konteks disebutkan di atas. Apa yang termasuk di dalamnya? Saat mengalihkan konteks, perlu untuk menyimpan register prosesor, untuk menghapus pipa instruksinya, untuk menghemat wilayah memori yang dialokasikan untuk proses. Secara umum, operasinya cukup mahal. Dibutuhkan ~ 0,5 μs, sementara eksekusi dari satu baris kode sederhana adalah ~ 1 ns. Selain itu, dengan peningkatan jumlah proses per inti prosesor, overhead untuk pengalihan konteks akan meningkat.

Model Server Web


Saat ini, ada model server web berikut:

  • pekerja
  • prefork
  • tidak sinkron
  • digabungkan


Mari kita bahas masing-masing secara terpisah.

Pekerja dan prefork


Secara historis, dengan model-model ini, semuanya dimulai. Intinya sangat sederhana : klien datang kepada kami, kami memilih penangan terpisah untuknya, yang memproses klien yang masuk dari awal hingga akhir. Pawang dapat berupa proses (prefork) atau utas (pekerja). Contoh dari server web semacam itu adalah Apache yang terkenal.

Saya akan segera melakukan reservasi: membuat penangan baru untuk setiap klien mahal. Pertama, dengan jumlah inti yang konstan, peningkatan jumlah prosesor menyebabkan peningkatan latensi (karena sakelar konteks). Kedua, jumlah memori yang dibutuhkan tumbuh secara linear dengan peningkatan klien, karena bahkan jika Anda menggunakan utas berbagi memori, setiap utas memiliki tumpukan sendiri. Dengan demikian, jumlah klien yang diproses secara bersamaan terbatas.ukuran pool, yang, pada gilirannya, tergantung pada jumlah core prosesor. Masalahnya diselesaikan dengan menggunakan metode penskalaan vertikal.

Kelemahan mendasar lain dari server tersebut adalah penggunaan sumber daya yang tidak optimal. Sebagian besar proses (atau utas) tidak digunakan . Bayangkan situasi berikut: selama pemrosesan klien, perlu untuk mengambil beberapa data dari hard drive, membuat permintaan ke database, atau menulis sesuatu ke jaringan. Karena membaca dari hard disk di Linux adalah operasi pemblokiran , proses (atau utas) akan menunggu respons, tetapi masih akan berpartisipasi dalam alokasi waktu prosesor.

Pekerja vs prefork


Pekerja dan prefork memiliki beberapa perbedaan mendasar. Streaming agak lebih ekonomis dalam memori karena mereka membagikannya. Untuk alasan yang sama, pergantian konteks di antara mereka lebih mudah daripada antar proses. Namun, dalam kasus pekerja, kode menjadi multi-utas, karena utas harus disinkronkan. Akibatnya, kami mendapatkan semua "pesona" kode multi-utas: menjadi lebih sulit untuk menulis, membaca, menguji dan men-debug-nya.

Model asinkron


Jadi, pekerja dan prefork tidak memungkinkan untuk memproses sejumlah besar klien pada saat yang sama karena ukuran kolam yang terbatas, dan juga tidak secara optimal menggunakan sumber daya karena pengalihan konteks dan pemblokiran panggilan sistem. Seperti yang Anda lihat, masalahnya adalah multithreading dan penjadwal OS yang berat. Ini mengarah pada gagasan berikut: mari kita proses klien hanya dalam satu utas, tetapi biarkan dimuat pada 100%.

Server semacam itu didasarkan pada loop peristiwa dan templat reaktor ( mesin acara ). Kode klien, yang memulai operasi I / O, mendaftarkan panggilan balikdalam antrian prioritas (prioritas adalah waktu kesiapan). Pengulangan acara jajak pendapat deskriptor menunggu I / O, dan kemudian memperbarui prioritas (jika tersedia) Selain itu, loop acara menarik acara dari antrian prioritas, memanggil panggilan balik yang mengembalikan kontrol ke loop acara di akhir.

Model ini memungkinkan Anda untuk menangani sejumlah besar klien, menghindari overhead'a untuk beralih konteks . Model ini tidak sempurna dan memiliki beberapa kelemahan. Pertama, tidak lebih dari satu inti prosesor yang dikonsumsi , karena hanya ada satu proses. Ini diperlakukan menggunakan model gabungan, yang akan dibahas di bawah ini. Kedua, pelanggan terhubung dengan proses ini.. Kode harus ditulis dengan hati-hati. Kebocoran memori, kesalahan mengarah pada kenyataan bahwa semua klien jatuh sekaligus. Selain itu, proses ini tidak boleh diblokir oleh apa pun, panggilan balik tidak harus terdiri dalam menyelesaikan beberapa tugas sulit, karena semua klien akan diblokir. Ketiga, kode asinkron jauh lebih rumit . Adalah perlu untuk mendaftarkan panggilan balik tambahan bahwa data tidak akan datang, untuk menyelesaikan masalah tentang cara melakukan percabangan yang benar, dll.

Model gabungan


Model ini digunakan di server nyata. Model ini memiliki kumpulan proses, masing-masing memiliki kumpulan benang, yang masing-masing, pada gilirannya, menggunakan model pemrosesan berdasarkan input-output asinkron. Nginx menghadirkan model gabungan.

Kesimpulan


Dengan demikian, beralih ke dasar-dasar sistem operasi, kami memeriksa perbedaan konseptual antara model server web yang digunakan di Apache dan Nginx. Masing-masing dari mereka memiliki kelebihan dan kekurangan, sehingga kombinasi mereka sering digunakan dalam produksi.

Gagasan pemrosesan asinkron telah berkembang lebih lanjut: pada tingkat platform bahasa, konsep benang hijau / serat / goroutine telah muncul, yang memungkinkan Anda untuk "menyembunyikan di balik tudung" asinkron input dan output, membuat pengembang senang dengan kode sinkron yang indah. Namun, konsep ini layak mendapat artikel terpisah.



Pelajari lebih lanjut tentang kursus.



All Articles