Saya bekerja pada aplikasi web yang agak besar, dan backend kebanyakan dalam PHP. Ada beberapa tempat dalam kode di mana saya perlu menyelesaikan beberapa tugas, tetapi saya tidak ingin membuat pengguna menunggu hasilnya. Misalnya, saat membuat akun baru, saya harus mengirim mereka email selamat datang. Tetapi ketika mereka menekan tombol 'Selesai Pendaftaran', saya tidak ingin membuat mereka menunggu sampai email benar-benar dikirim, saya hanya ingin memulai prosesnya, dan segera mengembalikan pesan kepada pengguna.
Sampai sekarang, di beberapa tempat saya telah menggunakan sesuatu yang terasa seperti hack dengan exec (). Pada dasarnya melakukan hal-hal seperti:
exec("doTask.php $arg1 $arg2 $arg3 >/dev/null 2>&1 &");
Yang tampaknya berhasil, tapi saya bertanya-tanya apakah ada cara yang lebih baik. Saya sedang mempertimbangkan untuk menulis sebuah sistem yang mengantri tugas-tugas dalam tabel MySQL, dan skrip PHP yang sudah berjalan lama yang menanyakan tabel itu satu kali per detik, dan menjalankan tugas-tugas baru yang ditemukannya. Ini juga akan memiliki keuntungan membiarkan saya membagi tugas di antara beberapa mesin pekerja di masa depan jika saya perlu.
Apakah saya menciptakan kembali roda? Apakah ada solusi yang lebih baik daripada hack exec () atau antrian MySQL?
sumber
Ketika Anda hanya ingin mengeksekusi satu atau beberapa permintaan HTTP tanpa harus menunggu respons, ada solusi PHP sederhana juga.
Dalam skrip panggilan:
Pada script.php yang disebut, Anda dapat menjalankan fungsi-fungsi PHP ini di baris pertama:
Ini menyebabkan skrip untuk terus berjalan tanpa batas waktu ketika koneksi HTTP ditutup.
sumber
Cara lain untuk proses garpu adalah melalui curl. Anda dapat mengatur tugas internal Anda sebagai layanan web. Sebagai contoh:
Kemudian di skrip yang diakses pengguna Anda melakukan panggilan ke layanan:
Layanan Anda dapat melacak antrian tugas dengan mysql atau apa pun yang Anda suka intinya adalah: semuanya sudah termasuk dalam layanan dan skrip Anda hanya menggunakan URL. Ini membebaskan Anda untuk memindahkan layanan ke mesin / server lain jika perlu (dengan mudah dapat diskalakan).
Menambahkan otorisasi http atau skema otorisasi khusus (seperti layanan web Amazon) memungkinkan Anda membuka tugas untuk dikonsumsi oleh orang / layanan lain (jika Anda mau) dan Anda bisa membawanya lebih jauh dan menambahkan layanan pemantauan di atas untuk melacak status antrian dan tugas.
Memang butuh sedikit kerja pengaturan tetapi ada banyak manfaat.
sumber
Saya telah menggunakan Beanstalkd untuk satu proyek, dan berencana untuk kembali. Saya menemukan ini sebagai cara terbaik untuk menjalankan proses asinkron.
Beberapa hal yang telah saya lakukan adalah:
Saya menulis sistem berbasis Zend-Framework untuk mendekode url yang 'bagus', jadi misalnya, untuk mengubah ukuran gambar yang akan dipanggil
QueueTask('/image/resize/filename/example.jpg')
. URL pertama kali diterjemahkan ke array (modul, controller, action, parameter), dan kemudian dikonversi ke JSON untuk injeksi ke antrian itu sendiri.Cli script yang berjalan lama kemudian mengambil pekerjaan dari antrian, menjalankannya (melalui Zend_Router_Simple), dan jika diperlukan, masukkan informasi ke dalam memcached untuk situs web PHP untuk mengambil sebagaimana diperlukan ketika itu selesai.
Satu kerutan yang saya lakukan juga adalah bahwa cli-script hanya berjalan selama 50 loop sebelum memulai kembali, tetapi jika memang ingin memulai kembali seperti yang direncanakan, itu akan segera melakukannya (dijalankan melalui bash-script). Jika ada masalah dan saya lakukan
exit(0)
(nilai default untukexit;
ataudie();
) pertama-tama akan berhenti selama beberapa detik.sumber
Jika hanya soal menyediakan tugas-tugas mahal, jika php-fpm didukung, mengapa tidak menggunakan
fastcgi_finish_request()
fungsi?Anda tidak benar-benar menggunakan asinkronisitas dengan cara ini:
fastcgi_finish_request()
.Sekali lagi diperlukan php-fpm.
sumber
Ini adalah kelas sederhana yang saya kodekan untuk aplikasi web saya. Ini memungkinkan untuk forking skrip PHP dan skrip lainnya. Bekerja pada UNIX dan Windows.
sumber
Ini adalah metode yang sama yang telah saya gunakan selama beberapa tahun sekarang dan saya belum melihat atau menemukan sesuatu yang lebih baik. Seperti yang dikatakan orang, PHP adalah single threaded, jadi tidak banyak yang bisa Anda lakukan.
Saya sebenarnya telah menambahkan satu level ekstra untuk ini dan itu mendapatkan dan menyimpan id proses. Ini memungkinkan saya untuk mengalihkan ke halaman lain dan membuat pengguna duduk di halaman itu, menggunakan AJAX untuk memeriksa apakah prosesnya sudah selesai (id proses sudah tidak ada lagi). Ini berguna untuk kasus di mana panjang skrip akan menyebabkan browser kehabisan waktu, tetapi pengguna harus menunggu skrip itu selesai sebelum langkah berikutnya. (Dalam kasus saya itu sedang memproses file ZIP besar dengan CSV seperti file yang menambahkan hingga 30.000 catatan ke database setelah itu pengguna perlu mengkonfirmasi beberapa informasi.)
Saya juga telah menggunakan proses serupa untuk pembuatan laporan. Saya tidak yakin saya akan menggunakan "pemrosesan latar belakang" untuk sesuatu seperti email, kecuali ada masalah nyata dengan SMTP yang lambat. Sebaliknya saya mungkin menggunakan tabel sebagai antrian dan kemudian memiliki proses yang berjalan setiap menit untuk mengirim email dalam antrian. Anda harus waspada mengirim email dua kali atau masalah serupa lainnya. Saya akan mempertimbangkan proses antrian yang sama untuk tugas-tugas lain juga.
sumber
PHP TELAH multithreading, tidak diaktifkan secara default, ada ekstensi yang disebut pthreads yang melakukan hal itu. Anda akan membutuhkan php yang dikompilasi dengan ZTS. Tautan (Utas Aman):
Contohnya
Tutorial lain
pthreads Ekstensi PECL
sumber
Merupakan ide bagus untuk menggunakan CURL seperti yang disarankan oleh rojoca.
Berikut ini sebuah contoh. Anda dapat memonitor text.txt saat skrip berjalan di latar:
sumber
Sayangnya PHP tidak memiliki kemampuan threading asli apa pun. Jadi saya pikir dalam hal ini Anda tidak punya pilihan selain menggunakan semacam kode khusus untuk melakukan apa yang ingin Anda lakukan.
Jika Anda mencari di internet untuk hal-hal threading PHP, beberapa orang telah menemukan cara untuk mensimulasikan thread pada PHP.
sumber
Jika Anda mengatur header HTTP Panjang Konten di respons "Terima Kasih Untuk Mendaftar", maka browser akan menutup koneksi setelah jumlah byte yang ditentukan diterima. Ini membiarkan proses sisi server berjalan (dengan anggapan ign_user_abort disetel) sehingga dapat selesai bekerja tanpa membuat pengguna akhir menunggu.
Tentu saja Anda perlu menghitung ukuran konten respons Anda sebelum merender tajuk, tetapi cukup mudah untuk tanggapan singkat (tulis keluaran ke string, panggil strlen (), panggil panggilan (), panggil tajuk (), render string).
Pendekatan ini memiliki keuntungan karena tidak memaksa Anda untuk mengelola antrian "ujung depan", dan meskipun Anda mungkin perlu melakukan beberapa pekerjaan di ujung belakang untuk mencegah balap proses anak HTTP saling menginjak, itu adalah sesuatu yang perlu Anda lakukan sudah bagaimanapun juga.
sumber
header('Content-Length: 3'); echo '1234'; sleep(5);
itu meskipun browser hanya membutuhkan 3 karakter, itu masih menunggu selama 5 detik sebelum menunjukkan respons. Apa yang saya lewatkan?phpinfo()
. Satu-satunya hal lain yang dapat saya bayangkan adalah bahwa saya harus mencapai ukuran buffer minimum terlebih dahulu, misalnya 256 atau lebih byte.Jika Anda tidak ingin ActiveMQ yang penuh sesak, saya sarankan untuk mempertimbangkan RabbitMQ . RabbitMQ adalah pesan ringan yang menggunakan standar AMQP .
Saya sarankan untuk juga melihat ke php-amqplib - pustaka klien AMQP yang populer untuk mengakses broker pesan berbasis AMQP.
sumber
Saya pikir Anda harus mencoba teknik ini. Ini akan membantu untuk memanggil sebanyak halaman yang Anda suka semua halaman akan berjalan sekaligus secara mandiri tanpa menunggu setiap respons halaman sebagai tidak sinkron.
cornjobpage.php // mainpage
testpage.php
PS: jika Anda ingin mengirim parameter url sebagai loop kemudian ikuti jawaban ini: https://stackoverflow.com/a/41225209/6295712
sumber
Memunculkan proses baru di server menggunakan
exec()
atau langsung di server lain menggunakan curl tidak skala semua sama sekali, jika kita pergi untuk eksekutif Anda pada dasarnya mengisi server Anda dengan proses berjalan lama yang dapat ditangani oleh server non web yang menghadap lainnya, dan menggunakan ikatan ikal ke server lain kecuali jika Anda membangun semacam load balancing.Saya telah menggunakan Gearman dalam beberapa situasi dan saya merasa lebih baik untuk kasus penggunaan semacam ini. Saya dapat menggunakan server antrian pekerjaan tunggal untuk menangani antrian pada semua pekerjaan yang perlu dilakukan oleh server dan memutar server pekerja, yang masing-masing dapat menjalankan sebanyak contoh proses pekerja sesuai kebutuhan, dan meningkatkan jumlah server pekerja sesuai kebutuhan dan putar ke bawah saat tidak diperlukan. Ini juga memungkinkan saya mematikan proses pekerja sepenuhnya saat diperlukan dan mengantre pekerjaan sampai pekerja kembali online.
sumber
PHP adalah bahasa single-threaded, jadi tidak ada cara resmi untuk memulai proses asinkron dengannya selain menggunakan
exec
ataupopen
. Ada posting blog tentang itu di sini . Gagasan Anda untuk antrian di MySQL juga merupakan ide bagus.Persyaratan khusus Anda di sini adalah untuk mengirim email ke pengguna. Saya ingin tahu mengapa Anda mencoba melakukan hal itu secara tidak sinkron karena mengirim email adalah tugas yang cukup sepele dan cepat untuk dilakukan. Saya kira jika Anda mengirim banyak email dan ISP Anda memblokir Anda karena dicurigai melakukan spamming, itu mungkin salah satu alasan untuk mengantri, tetapi selain itu saya tidak dapat memikirkan alasan untuk melakukannya dengan cara ini.
sumber