
Pemrograman asinkron sangat diminati saat ini, terutama dalam pengembangan web, di mana respons aplikasi sangat penting. Tidak ada yang mau menunggu aplikasi untuk "melorot", bahkan jika pada saat itu menjalankan query ke database, mengirim email atau bekerja pada tugas-tugas lain yang dapat memakan banyak waktu. Klien menginginkan jawaban atas tindakannya, yang terbaik dari semuanya - segera. Jika aplikasi Anda lambat, Anda kehilangan pelanggan. Dihadapkan dengan aplikasi melayang, paling sering pengguna hanya menutupnya dan tidak pernah kembali. Dari sudut pandang pengguna, aplikasi hanya hang, dia tidak bisa mengerti mengapa ini terjadi: apakah itu melakukan operasi yang kompleks atau telah berhenti bekerja pada prinsipnya.
Memperkenalkan terjemahan artikel oleh Skyend backend developer Sergey Zhuk.App Responsiveness
Aplikasi modern sering responsif, tetapi beberapa tugas atau operasi, seperti bertukar data melalui jaringan, file I / O, atau query database, dapat memakan waktu dan secara signifikan memperlambat aplikasi. Untuk mencegah operasi seperti memblokir aplikasi, Anda dapat menjalankannya di latar belakang, sehingga menyembunyikan penundaan yang disebabkannya. Pada saat yang sama, aplikasi tetap responsif karena dapat terus melakukan tugas-tugas lain, misalnya, mengembalikan aliran kontrol ke antarmuka pengguna atau merespons peristiwa lain.
Konkurensi dan Asinkron
Ketika orang melihat kode asinkron, paling sering mereka langsung berpikir: "Hebat, saya bisa memparalelkan proses!". Saya mungkin mengecewakan Anda, tetapi sebenarnya tidak. Sinkronisasi dan konkurensi bukanlah hal yang sama. Mungkin sulit untuk menangkap perbedaan ini, jadi mari kita coba mencari tahu.
Jika tugas dilakukan secara tidak sinkron, mereka tidak memblokir satu sama lain dan pelaksanaan satu tugas tidak tergantung pada penyelesaian tugas lainnya. Concurrency, pada gilirannya, menyiratkan peluncuran beberapa tugas terpisah secara bersamaan sebagai unit kerja independen.
Sinkronisasi:
Pergi dan selesaikan sendiri tugas itu. Beri tahu saya setelah selesai dan tunjukkan hasilnya. Pada saat ini, saya dapat terus melakukan pekerjaan saya.
Kode asinkron membutuhkan proses dependensi yang muncul selama pelaksanaan tugas, dan ini diimplementasikan menggunakan panggilan balik. Ketika tugas selesai, kode memberitahukan tugas lain. Kode asinkron pada dasarnya adalah tentang waktu tugas yang harus diselesaikan (urutan kejadian).

Concurrency:
Pekerjakan pekerja sebanyak yang Anda inginkan, dan bagikan tugas di antara mereka untuk menyelesaikannya lebih cepat, dan beri tahu saya ketika Anda selesai. Saya dapat terus melakukan hal-hal lain atau, jika tugas ini mendesak, saya akan tinggal dan menunggu sampai Anda kembali dengan hasilnya. Kemudian saya dapat menyusun hasil akhir dari semua karyawan. Eksekusi paralel seringkali membutuhkan lebih banyak sumber daya, jadi di sini pada dasarnya tergantung pada perangkat keras.

Untuk memahami perbedaan antara eksekusi asinkron dan paralel menggunakan contoh nyata, kami membandingkan dua server web populer: Apache dan Nginx. Mereka dengan sempurna menggambarkan perbedaan ini. Nginx menggunakan model asinkron berbasis peristiwa sementara Apache menggunakan utas paralel. Apache membuat utas baru untuk setiap koneksi tambahan, jadi di sini jumlah maksimum koneksi yang diizinkan tergantung pada jumlah memori yang tersedia dalam sistem. Ketika batas koneksi tercapai, Apache berhenti membuat koneksi tambahan. Faktor pembatas ketika mengkonfigurasi Apache adalah memori (ingat bahwa eksekusi paralel sering tergantung pada perangkat keras). Jika utas berhenti, klien menunggu respons hingga utas gratis dan dapat mengirim respons.
Nginx tidak berfungsi seperti Apache - tidak membuat utas baru untuk setiap permintaan yang masuk. Nginx memiliki alur kerja utama (atau beberapa pekerja, seringkali untuk satu prosesor ada satu alur kerja), yang merupakan single-threaded. Pekerja ini dapat memproses ribuan koneksi "secara bersamaan" dan melakukannya secara serempak, dalam satu utas, dan tidak secara paralel dalam beberapa utas.
Jadi, "asinkron" adalah bagaimana kita membangun sistem, itu adalah komposisi proses yang tidak tergantung satu sama lain. Yang dimaksud dengan "eksekusi paralel" adalah eksekusi beberapa proses pada saat yang bersamaan, sementara mereka mungkin terkait atau tidak. Dalam eksekusi asinkron, kami memproses beberapa tugas sekaligus, dan dalam eksekusi paralel, kami memulai beberapa proses sekaligus. Ini mungkin tampaknya hal yang sama, tetapi tidak. Asynchrony menggambarkan suatu struktur, paralelisme menggambarkan cara melakukannya.
Eksekusi asinkron dapat dibandingkan dengan perangkat I / O di komputer Anda (mouse, keyboard, display). Mereka semua dikelola oleh sistem operasi, tetapi masing-masing merupakan bagian independen dari kernel. Proses-proses ini tidak sinkron, bisa paralel, tetapi ini tidak perlu. Jadi, untuk memastikan konsistensi, Anda harus membuat tautan antara bagian-bagian independen ini untuk mengoordinasikannya.
Bagaimana dengan backend ini?
Anda dapat mengatakan bahwa respons tidak terlalu penting di backend. Semua hal asinkron keren dengan JavaScript ini terjadi di freeend, dan server Anda hanya merespons permintaan, jadi freeend harus bertanggung jawab atas respons aplikasi, tetapi bukan Anda. Ya, itu benar, tetapi tugas server tidak terbatas pada respons API. Terkadang Anda harus mengelola tugas yang rumit, misalnya mengunduh video. Dalam hal ini, responsif mungkin bukan faktor kunci, tetapi kurangnya sumber daya terbuang karena aplikasi harus diam. Itu bisa menunggu penyelesaian operasi sistem file, interaksi jaringan, permintaan basis data, dan sejenisnya. Seringkali operasi I / O ini sangat lambat dibandingkan dengan perhitungan prosesor, misalnya ketika kita mengonversi file video. Dan sementara kami perlahan menyimpan atau membaca file, prosesor dipaksa untuk siaga alih-alih melakukan pekerjaan yang bermanfaat. Seperti yang sudah kita ketahui, alih-alih menunggu, kita dapat menjalankan tugas ini di latar belakang. Bagaimana? Silakan.
PHP asinkron
Dalam JavaScript, di luar kotak, dukungan bawaan dan solusi untuk menulis kode asinkron tersedia. Ada juga Node.js, yang memungkinkan Anda untuk menulis aplikasi server asinkron. Dalam JavaScript, kita dapat menggunakan fungsi setTimeout () untuk menunjukkan contoh kode asinkron:

Ketika kita menjalankan kode ini, kita akan melihat yang berikut:

Fungsi setTimeout () mengirimkan kode ke antrian dan menjalankannya di akhir tumpukan panggilan saat ini. Ini berarti bahwa kami mengganggu aliran kode yang sinkron dan menunda eksekusi. Panggilan kedua ke console.log () dilakukan sebelum panggilan ke antrian di dalam panggilan setTimeout ().
Bagaimana dengan PHP? Dalam PHP, kami tidak memiliki alat adaptasi yang cocok untuk menulis kode yang benar-benar tidak sinkron. Tidak ada yang setara dengan setTimeout (), dan kami tidak bisa hanya menunda atau mengantri kode apa pun. Itu sebabnya kerangka kerja dan pustaka seperti Amp dan ReactPHP mulai muncul. Gagasan mereka adalah menyembunyikan detail tingkat rendah bahasa dan memberikan alat tingkat tinggi kepada pengguna yang memungkinkan Anda untuk menulis kode asinkron dan mengelola eksekusi proses kompetitif seperti JavaScript dan Node.js.
Mengapa saya harus menggunakan PHP jika ada Node.js dan Go?
Pertanyaan ini sering muncul ketika datang ke PHP asinkron. Untuk beberapa alasan, banyak yang menentang menggunakan PHP untuk menulis kode asinkron. Seseorang selalu menyarankan menggunakan Go atau Node.js. sebagai ganti PHP.
Tweet assertchris dengan sempurna menjelaskan situasi ini:

Tentu saja, ketika PHP baru saja dibuat, tidak ada tujuan untuk menjadikannya bahasa pemrograman yang dapat digunakan untuk membuat aplikasi rumit yang besar. Saat itu, tidak ada yang memikirkan JavaScript atau asynchrony. Tetapi sekarang kami memiliki PHP yang sama sekali berbeda yang sudah memiliki fungsinya sendiri untuk menulis kode asinkron (misalnya, fungsi stream_select ()).
Ya, Anda bisa menggunakan Go atau Node.js untuk membuat aplikasi server asinkron, tetapi ini tidak selalu menyelesaikan masalah. Jika Anda sudah memiliki pengalaman luas dengan PHP, akan jauh lebih mudah bagi Anda untuk hanya mempelajari perpustakaan dan alat-alat yang sesuai untuk situasi Anda daripada belajar bahasa baru dan ekosistem baru. Alat-alat seperti
ReactPHP atau
Amp memungkinkan Anda untuk menulis kode asinkron seperti Anda melakukannya di Node.js. Alat-alat ini cukup dikembangkan dan memiliki versi stabil, sehingga Anda dapat menggunakannya dengan aman dalam produksi.
Bukan hanya CLI
Saya tidak akan menulis obrolan, server atau sesuatu seperti itu. Saya hanya ingin mempercepat situs.
Secara umum diterima bahwa kode asinkron hanya dapat digunakan dalam skrip CLI. Sangat normal untuk mengintegrasikan beberapa komponen asinkron ke dalam lingkungan sinkron tradisional, bahkan ke dalam aplikasi web tradisional. Misalnya, Anda dapat menerima permintaan dan kemudian memanggil beberapa sumber yang berbeda secara tidak sinkron, dan ketika panggilan ini selesai, Anda dapat melanjutkan siklus hidup permintaan-respons, dan sebagai hasilnya, halaman tersebut akan ditampilkan lebih cepat.
Atau Anda perlu melakukan beberapa panggilan API eksternal - misalnya, ketika pengguna menyelesaikan pembayaran, Anda ingin mengirim email atau pemberitahuan push. Anda dapat membuat panggilan API ini secara tidak sinkron, dan kemudian melanjutkan aliran kode sinkron tradisional Anda. Tidak perlu sepenuhnya menulis ulang aplikasi dan menghapus semua yang memperlambat. Identifikasi saja kemacetan yang mengganggu kinerja, dan mungkin saja mereka dapat diperbaiki menggunakan kode asinkron.
Ya, kode asinkron dalam banyak kasus masih digunakan dalam skrip CLI, tetapi tidak terbatas pada obrolan dan server waktu nyata. Jika Anda hanya ingin mempercepat situs Anda, Anda tidak perlu menyerahkan kerangka kerja Symfony atau Laravel Anda dan membuat server aplikasi yang sepenuhnya tidak sinkron.
Kesimpulan
Jangan takut untuk belajar paradigma baru. PHP lebih dari sekadar "menjalankan skrip, menjalankan kode, dan mati." Anda akan terkejut ketika Anda menyadari bahwa Anda dapat menggunakan PHP yang akrab dengan cara yang sama sekali baru, seperti Anda tidak pernah menggunakannya! Kode asinkron dan pemrograman berorientasi peristiwa akan memperluas pemahaman Anda tentang PHP dan kemungkinan menggunakan bahasa ini. Anda tidak perlu belajar bahasa baru untuk menulis aplikasi asinkron hanya karena "PHP adalah alat yang tidak pantas" atau "Saya selalu melakukan ini, itu tidak dapat diperbaiki." Cobalah!
Yah, kami juga mengingatkan Anda bahwa kami selalu memiliki banyak
lowongan menarik untuk pengembang!