Ini adalah artikel dari dunia Python, tetapi masih berlaku untuk seluruh bidang pemrograman, meskipun multithreading memungkinkan kita untuk memproses permintaan lebih cepat, tetapi ada juga langit-langit, utas hijau (micro-thread) adalah solusinya.
Pengembangan perangkat lunak multithread memecahkan sejumlah besar masalah, terutama untuk aplikasi yang berpusat pada jaringan yang membutuhkan kinerja yang menuntut untuk merespons pengguna dengan cepat. Sayangnya, multithreading tidak cukup untuk menyelesaikan skala besarKonkurensimasalah seksual.
Mengatasi masalah ini memerlukan perubahan model pemrograman, menggunakan peristiwa asinkron dan mekanisme berbasis callback. Di Druva, kami membuat perpustakaan berbasis python yang disebut Dhaga untuk memecahkan skala besarKonkurensi, sementara model pemrograman tidak memerlukan perubahan yang signifikan.
Pengembang perangkat lunak tinggal dalam satuKonkurensidunia. Utas adalah warga kelas satu saat ini, terutama selama pengembangan, terutama ketika aplikasi Anda melakukan operasi jaringan intensif, seperti sistem inSync (produk sinkronisasi keamanan jaringan) seperti Druva. Multithreading membantu aliran kode pemrograman untuk operasi jaringan dengan sederhana dan teratur. Ketika aplikasi kita membutuhkan peningkatan atau peningkatan kinerja, itu dapat ditingkatkanElastisitas, kita dapat meningkatkan jumlah utas.
Tetapi ketika menyangkut ribuan timbanganKonkurensipermintaan, utas tidak cukup.
Kami menemukan bahwa multithreading memiliki kelemahan berikut: 1. Klien sistem inSync perlu mencadangkan sejumlah besar file ke server melalui panggilan RPC jaringan. Cara khas bagi pengembang untuk mempercepat segalanya adalah dengan menggunakan utas. Namun, kinerja yang dibawa oleh multi-threading meningkatkan biaya memori dan CPU; Pengembang perlu menjaga keseimbangan antara kecepatan dan jumlah utas.
2. Server kami perlu menangani antara sistem inSync dan ribuan pelangganKonkurensiKoneksi dan pemberitahuan. Untuk menangani koneksi secara efisien, kami menggunakan utas untuk menangani permintaan. Tetapi meningkatnya jumlah pelanggan sistem inSync juga berarti bahwa kita harus terus meningkatkan jumlah utas, yang menghabiskan banyak memori server dan CPU.
3. Server web kami perlu menangani ribuan permintaan HTTP paralel. Sebagian besar pekerjaan ada di soket jaringan yang menerima dan mengirim data dan meneruskannya ke backend sistem inSync. Menyebabkan sebagian besar utas menunggu operasi jaringan. Menyebabkan masalah C10K, ketika ada ribuan permintaan sinkron ke server web, menghasilkan utas untuk setiap permintaan cukup tidak dapat diskalakan (Skala).
Keterbatasan kerangka kerja asinkron Banyak kerangka kerja asinkron, termasuk Twisted, Tornado Tornado, dan asyncore, dapat membantu pengembang menjauh dari cara populer dalam menggunakan utas. Kerangka kerja ini mengandalkan soket non-pemblokiran dan mekanisme panggilan balik (mirip dengan Node.js). Jika kita menggunakan kerangka kerja ini apa adanya, bagian utama dari kode Druva kita harus difaktorkan ulang. Bukan itu yang ingin kami lakukan. Memfaktorkan ulang kode meningkatkan siklus pengembangan dan pengujian, mencegah kami memenuhi persyaratan skala kami. Mengingat bahwa beberapa bagian produk harus besar, masing-masing dari kita harus memfaktorkannya ulang – oleh karena itu upaya untuk menggandakan atau melipatgandakan.
Untuk menghindari perubahan begitu banyak kode, kami harus menjauh dari penggunaan kerangka kerja yang ada secara langsung. Untungnya, kami menemukan beberapa alat yang berguna.
Karena kita ingin mengontrol eksekusi kode pada I/O jaringan, kita membutuhkan cara untuk membagi utas menjadi utas mikro. Kami menemukansayuran hijau。 Ini menyediakan penjadwalan microthread non-implisit yang disebut coroutine co-routine. Dengan kata lain. Ini berguna saat Anda ingin mengontrol kode yang berjalan. Anda dapat membuat microthread untuk jadwal kustom karena Anda dapat mengontrol kapan hasil greenlet dijeda. Ini sempurna untuk kami karena memberi kami kendali penuh atas penjadwalan kode kami.
Tornado adalah kerangka kerja server web sederhana dan non-pemblokiran yang ditulis dalam Python yang dirancang untuk menangani ribuan permintaan asinkron. Kami menggunakan komponen intinya, IOLoop IOStream. IOLoop adalah loop peristiwa I/O soket non-pemblokiran; Ini menggunakan epoll (di Linux) atau antrian (BSD dan Mac OS X), jika tidak, pilih (di Windows) jika tersedia. IOStream menyediakan soket non-pemblokiran seperti kemasan yang nyaman untuk membaca dan menulis. Kami mendelegasikan semua operasi soket ke Tornado dan kemudian menggunakan callback untuk memicu operasi kode untuk diselesaikan (catatan banq: sangat mirip dengan mekanisme Node.js).
Ini awal yang baik, tetapi kami membutuhkan lebih banyak. Jika kita menggunakan modul di atas langsung di kode kita, banyak kode RPC kita harus diubah, menjadwalkan RPC melalui greenlets, memastikan greenlet tidak memblokir (jika greenlet tersumbat, itu akan menyumbat seluruh utas dan semua yang lainnya), menangani fungsi callback dari tornado.
Kita membutuhkan abstraksi untuk mengelola dan mengatur greenlet untuk menghindari penyumbatan mereka dengan panggilan eksternal, dan abstraksi ini dapat diskalakan secara besar-besaran di luar utas. Abstraksi ini adalah Dhaga, yang memungkinkan aliran kode aplikasi diprogram seperti urutan sinkron tradisional, tetapi eksekusinya asinkron.
Dhaga (dari bahasa Hindi, yang berarti utas) adalah kerangka kerja eksekusi untuk utas ringan yang kita abstraksikan. Kelas Dhaga berasal dari greenlet dan menggunakan stack switching untuk mengeksekusi beberapa aliran kode dalam satu utas sistem operasi. Utas dari satu sistem operasi mengeksekusi beberapa dhagas menggunakan penjadwalan kolaboratif. Setiap kali dhaga menunggu (terutama menunggu panggilan RPC kembali), itu menghasilkan kontrol ke tingkat induk (yaitu, konteks eksekusi utas tingkat OS yang membuatnya). Level induk kemudian menjadwalkan dhaga lain agar siap dijalankan. Panggilan RPC akan diteruskan ke server web tornado untuk menulis Socket secara asinkron, dan kemudian mendaftarkan callback ketika kembali, dan ketika RPC ini kembali, dhaga yang menunggu akan ditambahkan ke antrean yang dapat dieksekusi dan kemudian diambil oleh utas induk. (Catatan Banq: mirip dengan prinsip node.js)
Kita dapat menggunakan Dhaga sebagai pengganti thread untuk operasi latensi tinggi, dan kita menggunakan 512 dhaga dalam satu thread ketika jumlah thread meningkat melebihi batas yang wajar untuk throughput.
|