Saya mencoba memahami detail server web yang lebih rendah. Saya bertanya-tanya apakah server, katakanlah Apache, terus-menerus mengumpulkan suara untuk permintaan baru atau Jika itu bekerja dengan semacam sistem interupsi. Jika interupsi, apa yang memicu interupsi, apakah itu driver kartu jaringan?
networking
webserver
embedded
pengguna2202911
sumber
sumber
Jawaban:
Jawaban singkatnya adalah: semacam sistem interupsi. Intinya, mereka menggunakan pemblokiran I / O, artinya mereka tidur (block) sambil menunggu data baru.
Server membuat soket pendengaran dan kemudian memblokir sambil menunggu koneksi baru. Selama waktu ini, kernel menempatkan proses ke dalam status sleep yang interruptible dan menjalankan proses lainnya. Ini adalah poin penting: memiliki proses jajak pendapat yang terus menerus akan membuang-buang CPU. Kernel dapat menggunakan sumber daya sistem dengan lebih efisien dengan memblokir proses sampai ada pekerjaan yang harus dilakukan.
Ketika data baru tiba di jaringan, kartu jaringan mengeluarkan interupsi.
Melihat ada gangguan dari kartu jaringan, kernel, melalui driver kartu jaringan, membaca data baru dari kartu jaringan dan menyimpannya ke dalam memori. (Ini harus dilakukan dengan cepat dan umumnya ditangani di dalam interrupt handler.)
Kernel memproses data yang baru tiba dan mengaitkannya dengan soket. Suatu proses yang memblokir pada soket itu akan ditandai runnable, artinya sekarang layak untuk dijalankan. Itu tidak harus langsung berjalan (kernel mungkin memutuskan untuk menjalankan proses lainnya).
Pada waktu senggang, kernel akan membangunkan proses server web yang diblokir. (Karena sekarang bisa dijalankan.)
Proses server web terus mengeksekusi seolah-olah tidak ada waktu berlalu. Panggilan sistem pemblokirannya kembali dan memproses data baru. Lalu ... lanjutkan ke langkah 1.
sumber
accept
. Mereka (untungnya, atau itu akan benar-benar menyedot!) Mandiri, menjalankan tugas yang tidak sinkron. Saat koneksi masuk, mereka ditempatkan ke dalam antrian tempataccept
menariknya. Hanya jika tidak ada, itu menghalangi.Ada cukup banyak detail "lebih rendah".
Pertama, pertimbangkan bahwa kernel memiliki daftar proses, dan pada waktu tertentu, beberapa proses ini sedang berjalan, dan beberapa tidak. Kernel memungkinkan setiap proses yang berjalan beberapa waktu CPU, kemudian menyela dan pindah ke yang berikutnya. Jika tidak ada proses yang dapat dijalankan, maka kernel mungkin akan mengeluarkan instruksi seperti HLT ke CPU yang menangguhkan CPU sampai ada gangguan perangkat keras.
Di suatu tempat di server adalah panggilan sistem yang mengatakan "beri aku sesuatu untuk dilakukan". Ada dua kategori luas cara ini bisa dilakukan. Dalam kasus Apache, ia memanggil
accept
soket yang sebelumnya telah dibuka oleh Apache, mungkin mendengarkan pada port 80. Kernel mempertahankan antrian upaya koneksi, dan menambahkan ke antrian itu setiap kali TCP SYN diterima. Bagaimana kernel mengetahui TCP SYN diterima tergantung pada driver perangkat; untuk banyak NIC mungkin ada interupsi perangkat keras ketika data jaringan diterima.accept
meminta kernel untuk kembali kepada saya inisiasi koneksi berikutnya. Jika antrian tidak kosong, makaaccept
segera kembali segera. Jika antrian kosong, maka proses (Apache) dihapus dari daftar proses yang berjalan. Ketika suatu koneksi kemudian dimulai, proses dilanjutkan. Ini disebut "blocking", karena untuk proses memanggilnya,accept()
tampak seperti fungsi yang tidak kembali sampai hasilnya, yang mungkin beberapa waktu dari sekarang. Selama waktu itu proses tidak dapat melakukan hal lain.Setelah
accept
kembali, Apache tahu bahwa seseorang sedang mencoba untuk memulai koneksi. Itu kemudian memanggil garpu untuk membagi proses Apache dalam dua proses yang identik. Salah satu dari proses ini berlanjut untuk memproses permintaan HTTP, panggilan lainaccept
lagi untuk mendapatkan koneksi berikutnya. Jadi, selalu ada proses utama yang tidak melakukan apa-apa selain memanggilaccept
dan menelurkan sub-proses, dan kemudian ada satu sub-proses untuk setiap permintaan.Ini adalah penyederhanaan: dimungkinkan untuk melakukan ini dengan utas alih-alih proses, dan juga mungkin untuk
fork
sebelumnya sehingga ada proses pekerja siap untuk pergi ketika permintaan diterima, sehingga mengurangi overhead startup. Tergantung pada bagaimana Apache dikonfigurasikan, ia dapat melakukan hal-hal ini.Itulah kategori luas pertama cara melakukannya, dan itu disebut memblokir IO karena sistem memanggil suka
accept
danread
danwrite
yang beroperasi pada soket akan menunda proses sampai mereka memiliki sesuatu untuk dikembalikan.Cara lain yang luas untuk melakukannya disebut non-blocking atau event-based atau asynchronous IO . Ini diimplementasikan dengan panggilan sistem seperti
select
atauepoll
. Masing-masing melakukan hal yang sama: Anda memberi mereka daftar soket (atau secara umum, deskriptor file) dan apa yang ingin Anda lakukan dengan mereka, dan kernel memblokir hingga siap untuk melakukan salah satu dari hal-hal itu.Dengan model ini, Anda dapat memberi tahu kernel (dengan
epoll
), "Beri tahu saya ketika ada koneksi baru pada port 80 atau data baru untuk membaca pada salah satu dari 9471 ini koneksi lain yang saya buka".epoll
menghalangi sampai salah satu dari hal-hal itu siap, maka Anda melakukannya. Lalu kamu ulangi. Panggilan sistem sepertiaccept
danread
danwrite
tidak pernah memblokir, sebagian karena setiap kali Anda memanggil mereka,epoll
hanya mengatakan kepada Anda bahwa mereka siap sehingga tidak akan ada alasan untuk memblokir, dan juga karena ketika Anda membuka soket atau file yang Anda tentukan bahwa Anda menginginkannya dalam mode non-pemblokiran, sehingga panggilan tersebut akan gagal denganEWOULDBLOCK
alih - alih memblokir.Keuntungan dari model ini adalah Anda hanya perlu satu proses. Ini berarti Anda tidak perlu mengalokasikan struktur stack dan kernel untuk setiap permintaan. Nginx dan HAProxy menggunakan model ini, dan itu adalah alasan besar mereka dapat menangani lebih banyak koneksi daripada Apache pada perangkat keras yang sama.
sumber