Banyak Blocking VS Pekerja Non-Blocking Tunggal


9

Anggap ada server HTTP yang menerima koneksi dan entah bagaimana menunggu header dikirim sepenuhnya. Saya bertanya-tanya apa cara paling umum untuk mengimplementasikannya dan apa kelebihan dan kelemahannya. Saya hanya bisa memikirkan ini:

Banyak pekerja yang memblokir itu baik karena:

  • Itu lebih responsif.
  • Lebih mudah untuk memperkenalkan koneksi baru (pekerja mengambilnya sendiri daripada orang luar menunggu sampai dapat menambahkannya ke daftar yang disinkronkan).
  • Penggunaan CPU menyeimbangkan secara otomatis (tanpa upaya tambahan) karena jumlah koneksi meningkat dan menurun.
  • Lebih sedikit penggunaan CPU (utas yang diblokir dikeluarkan dari loop eksekusi dan tidak memerlukan logika apa pun untuk berpindah antar klien).

Pekerja non-blocking tunggal baik karena:

  • Menggunakan lebih sedikit memori.
  • Kurang rentan terhadap klien yang malas (yang terhubung ke server dan mengirim header secara lambat atau tidak mengirim sama sekali).

Seperti yang mungkin Anda lihat, menurut pendapat saya beberapa utas pekerja tampaknya solusi yang sedikit lebih baik secara keseluruhan. Satu-satunya masalah dengan itu adalah lebih mudah untuk menyerang server tersebut.

Sunting (penelitian lebih lanjut): Beberapa sumber daya yang saya temukan di web ( Ribuan Utas dan Pemblokiran I / O - Cara lama untuk menulis Server Java adalah Baru lagi (dan jauh lebih baik) oleh Paul Tyma) mengisyaratkan bahwa pendekatan pemblokiran umumnya lebih baik tetapi Saya masih tidak benar-benar tahu bagaimana menangani koneksi palsu.

PS Jangan menyarankan menggunakan beberapa pustaka atau aplikasi untuk tugas tersebut. Saya lebih tertarik mengetahui bagaimana cara kerjanya atau mungkin bekerja daripada membuatnya bekerja.

PSS Saya telah membagi logika menjadi beberapa bagian dan ini hanya menangani penerimaan header HTTP. Tidak memprosesnya.


Lo, bertahun-tahun yang lalu, saya menulis server berulir dengan memblokir I / O, karena mudah untuk menulis. Seorang kolega menulis jenis lain, dan itu berhasil dengan mengagumkan. Mereka adalah dua bentuk penawaran produk utama di perusahaan tempat saya dulu bekerja. Untuk "klien malas" dalam skenario pemblokiran, Anda dapat memiliki batas waktu penerimaan data.

Jawaban:


4

Tidak ada peluru perak

Dalam praktiknya itu tergantung ...

tl; dr - solusi mudah, gunakan nginx ...

Pemblokiran:

Misalnya, Apache secara default menggunakan skema pemblokiran tempat proses bercabang untuk setiap koneksi. Itu berarti setiap koneksi memerlukan ruang memori sendiri dan jumlah overhead konteks switching yang lebih meningkat seiring dengan meningkatnya jumlah koneksi. Tetapi manfaatnya adalah, sekali koneksi ditutup konteksnya dapat dibuang dan semua / semua memori dapat dengan mudah diambil.

Pendekatan multi-threaded akan serupa dalam hal overhead switching konteks meningkat dengan jumlah koneksi tetapi mungkin lebih efisien memori dalam konteks bersama. Masalah dengan pendekatan semacam itu adalah sulit untuk mengelola memori bersama dengan cara yang aman. Pendekatan untuk mengatasi masalah sinkronisasi memori sering termasuk overhead mereka sendiri, misalnya penguncian dapat membekukan utas pada beban intensif CPU, dan menggunakan tipe yang tidak dapat diubah menambah banyak penyalinan data yang tidak perlu.

AFAIK, menggunakan pendekatan multi-proses pada server HTTP pemblokiran umumnya lebih disukai karena lebih aman / sederhana untuk mengelola / memulihkan memori dengan cara yang aman. Pengumpulan sampah menjadi masalah ketika memulihkan memori semudah menghentikan suatu proses. Untuk proses yang berjalan lama (yaitu daemon) karakteristik itu sangat penting.

Sementara overhead pengalihan konteks mungkin tampak tidak signifikan dengan sejumlah kecil pekerja, kerugian menjadi lebih relevan karena beban meningkat hingga ratusan hingga ribuan koneksi bersamaan. Paling-paling, konteks mengubah skala O (n) ke jumlah pekerja yang hadir tetapi dalam praktiknya kemungkinan besar lebih buruk.

Di mana server yang menggunakan pemblokiran mungkin bukan pilihan ideal untuk beban berat IO, mereka ideal untuk pekerjaan intensif CPU dan pesan yang lewat disimpan ke minumum.

Non-Blok:

Non-blocking akan seperti Node.js atau nginx. Ini terutama dikenal untuk penskalaan ke jumlah koneksi yang jauh lebih besar per node di bawah beban intensif IO. Pada dasarnya, begitu orang mencapai batas atas dari apa yang dapat ditangani oleh server berbasis thread / proses, mereka mulai mengeksplorasi opsi alternatif. Ini juga dikenal sebagai masalah C10K (yaitu kemampuan untuk menangani 10.000 koneksi bersamaan).

Server async non-blocking umumnya memiliki banyak karakteristik dengan pendekatan multi-threaded-with-locking karena Anda harus berhati-hati untuk menghindari beban intensif CPU karena Anda tidak ingin membebani utas utama. Keuntungannya adalah bahwa overhead yang ditimbulkan oleh pengalihan konteks pada dasarnya dihilangkan dan dengan hanya satu pengiriman pesan konteks menjadi non-masalah.

Meskipun mungkin tidak berfungsi untuk banyak protokol jaringan, sifat stateless HTTPs berfungsi dengan baik terutama untuk arsitektur yang tidak menghalangi. Dengan menggunakan kombinasi reverse-proxy dan beberapa server HTTP non-pemblokiran, dimungkinkan untuk mengidentifikasi dan merutekan di sekitar node yang mengalami beban berat.

Bahkan pada server yang hanya memiliki satu node, sangat umum untuk pengaturan untuk memasukkan satu server per inti prosesor untuk memaksimalkan throughput.

Kedua:

Kasus penggunaan 'ideal' akan menjadi kombinasi dari keduanya. Proxy terbalik di bagian depan didedikasikan untuk merutekan permintaan di atas, kemudian campuran server yang memblokir dan yang tidak memblokir. Non-pemblokiran untuk tugas-tugas IO seperti melayani konten statis, konten cache, konten html. Memblokir untuk tugas-tugas berat CPU seperti penyandian gambar / video, konten streaming, angka-angka, penulisan basis data, dll.

Dalam kasus Anda:

Jika Anda hanya memeriksa tajuk tetapi sebenarnya tidak memproses permintaan, yang pada dasarnya Anda gambarkan adalah proksi terbalik. Dalam kasus seperti itu saya pasti akan pergi dengan pendekatan async.

Saya sarankan memeriksa dokumentasi untuk proksi terbalik bawaan nginx .

Ke samping:

Saya membaca tulisan dari tautan yang Anda berikan dan masuk akal bahwa async adalah pilihan yang buruk untuk implementasi khusus mereka. Masalahnya dapat diringkas dalam satu pernyataan.

Ditemukan bahwa ketika beralih di antara klien, kode untuk menyimpan dan mengembalikan nilai / status sulit

Mereka sedang membangun platform negara. Dalam kasus seperti itu, pendekatan async akan berarti bahwa Anda harus terus menyimpan / memuat status setiap kali konteks beralih (yaitu ketika suatu peristiwa diaktifkan). Selain itu, di sisi SMTP mereka melakukan banyak pekerjaan intensif CPU.

Sepertinya mereka memiliki pemahaman yang buruk tentang async dan, sebagai akibatnya, membuat banyak asumsi buruk.

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.