Rumah >pembangunan bahagian belakang >tutorial php >Dilahirkan untuk kelajuan: gabungan PHP dan Golang - RoadRunner

Dilahirkan untuk kelajuan: gabungan PHP dan Golang - RoadRunner

青灯夜游
青灯夜游ke hadapan
2022-09-23 19:40:455863semak imbas

Dilahirkan untuk kelajuan: gabungan PHP dan Golang - RoadRunner

Sejak dekad yang lalu, kami telah membangunkan apl untuk Fortune 500 syarikat dan perniagaan dengan 500 pengguna atau kurang. Dari segi sejarah, jurutera kami menggunakan PHP terutamanya untuk membangunkan bahagian belakang. Tetapi dua tahun lalu, beberapa isu timbul yang menjejaskan bukan sahaja prestasi produk kami, tetapi juga kebolehskalaan mereka - jadi kami memperkenalkan Golang (Go) ke dalam timbunan teknologi kami.

Hampir serentak, kami mendapati bahawa Go bukan sahaja membenarkan kami mencipta aplikasi yang lebih besar, tetapi juga meningkatkan prestasi sehingga 40x. Dengan itu, kami dapat memanjangkan produk sedia ada yang ditulis dalam PHP dan menambah baiknya dengan menggabungkan yang terbaik daripada kedua-dua bahasa.

Kami akan memberitahu anda melalui banyak pengalaman Go dan PHP, cara menggunakannya untuk menyelesaikan masalah pembangunan sebenar, dan bagaimana kami boleh mengubahnya menjadi alat untuk menghapuskan Model Kematian PHP beberapa soalan.

Persekitaran pembangunan PHP konvensional

Sebelum memberitahu cara Go menambah baik model kematian PHP, mari kita fahami persekitaran pembangunan PHP konvensional.

Biasanya, aplikasi dijalankan pada nginx dan PHP-FPM. nginx mengendalikan permintaan statik, manakala permintaan dinamik dialihkan ke PHP-FPM, yang melaksanakan kod PHP. Mungkin anda menggunakan Apache dan mod_php, tetapi mereka mempunyai prinsip yang sama dan hanya sedikit perbezaan dalam cara ia berfungsi.

Lihat cara PHP-FPM melaksanakan kod. Apabila permintaan diterima, PHP-FPM memulakan subproses PHP dan memajukan butiran permintaan kepadanya sebagai sebahagian daripada statusnya (_GET, _POST, _SERVER, dll.).

Semasa pelaksanaan skrip PHP, keadaan tidak boleh diubah, jadi hanya ada satu cara untuk mendapatkan set data input baharu: kosongkan memori proses dan mulakan semula.

Model prestasi ini mempunyai banyak kelebihan. Anda tidak perlu terlalu risau tentang penggunaan memori, semua proses diasingkan sepenuhnya, jika salah satu proses "mati", ia akan dicipta semula secara automatik dan tidak akan menjejaskan proses lain. Walau bagaimanapun, pendekatan ini mempunyai kelemahan apabila anda cuba menskalakan aplikasi anda.

Kelemahan dan Ketidakcekapan Persekitaran PHP Biasa

Jika anda membangun secara profesional dalam PHP, maka anda tahu di mana hendak bermula apabila mencipta projek baharu - Memilih Rangka Kerja . Ia adalah perpustakaan untuk suntikan pergantungan, ORM, transformasi dan kaedah templat. Sudah tentu, semua data yang dimasukkan pengguna boleh diletakkan dengan mudah dalam satu objek (Symfony / HttpFoundation atau PSR-7). Bingkai ini hebat!

Tetapi semuanya ada harganya. Dalam mana-mana rangka kerja perusahaan, untuk mengendalikan permintaan pengguna yang mudah atau mengakses pangkalan data, anda perlu memuatkan sekurang-kurangnya beberapa dozen fail, mencipta banyak kelas dan menghuraikan berbilang konfigurasi. Tetapi perkara yang paling teruk ialah selepas setiap tugas selesai, anda perlu menetapkan semula semuanya dan mulakan semula: semua kod yang baru anda mulakan akan menjadi tidak berguna, dan dengan bantuannya anda tidak akan dapat memproses permintaan lain. Beritahu perkara ini kepada mana-mana pengaturcara yang menulis dalam bahasa lain - dan anda akan melihat kekeliruan di wajahnya.

Selama bertahun-tahun, jurutera PHP telah mencari cara untuk menyelesaikan masalah ini, menggunakan teknik pemuatan malas, bingkai mikro, perpustakaan pengoptimuman, caching dan banyak lagi. Tetapi akhirnya, anda masih perlu meninggalkan keseluruhan aplikasi dan memulakan semula* (Nota Penterjemah: Dengan kemunculan pramuat dalam PHP7.4, masalah ini akan diselesaikan sebahagiannya) Kendalikan berbilang permintaan?

Anda boleh menulis skrip PHP yang bertahan lebih lama daripada beberapa minit (sehingga jam atau hari): mis. Semua kerja ini mengikut corak: mereka mendapat tugas, memprosesnya, dan kemudian mendapat tugasan seterusnya. Kod tersebut berada dalam ingatan, jadi operasi tambahan untuk memuatkan rangka kerja dan aplikasi dielakkan, menjimatkan masa yang berharga.

Tetapi membangunkan skrip jangka panjang bukanlah semudah itu. Sebarang ralat akan mematikan proses, limpahan memori akan menyebabkan ranap sistem dan anda tidak lagi boleh menggunakan F5 untuk nyahpepijat atur cara.

Perkara telah bertambah baik sejak PHP 7: pengumpul sampah yang boleh dipercayai telah muncul, ia menjadi lebih mudah untuk mengendalikan ralat, dan sambungan pada kernel boleh mengelakkan kebocoran memori. Ya, jurutera masih perlu berhati-hati menangani isu memori dan mengingati keadaan dalam kod (bahasa apa yang membolehkan anda tidak memberi perhatian kepada perkara ini?) Sudah tentu, dalam PHP 7, tidak banyak kejutan.

Adakah mungkin untuk menggunakan model skrip PHP pemastautin untuk tugasan yang lebih remeh seperti mengendalikan permintaan HTTP, dengan itu menghapuskan keperluan untuk memuat turun segala-galanya dari awal untuk setiap permintaan?

Untuk menyelesaikan masalah ini, anda perlu terlebih dahulu melaksanakan aplikasi pelayan yang boleh menerima permintaan HTTP dan mengubah halanya kepada pekerja PHP satu demi satu dan bukannya mematikannya setiap kali.

Kami tahu bahawa kami boleh menulis pelayan web dalam PHP tulen (PHP-PM) atau dengan sambungan C (Swoole). Walaupun setiap pendekatan mempunyai kelebihannya, tiada pilihan yang berkesan untuk kami - saya mahukan sesuatu yang lebih. Kami memerlukan lebih daripada sekadar pelayan web - kami mahukan penyelesaian yang membolehkan kami mengelakkan masalah yang berkaitan dengan "mula semula" dalam PHP, sambil mudah disesuaikan dan boleh dilanjutkan untuk aplikasi tertentu. Iaitu, kita memerlukan pelayan aplikasi.

Bolehkah Go membantu menyelesaikan masalah ini? Kami tahu ia boleh kerana bahasa itu menyusun aplikasi ke dalam satu binari; ia adalah platform merentas (concurrency) dan perpustakaannya sendiri untuk mengendalikan HTTP dan akhirnya, kami boleh meletakkan lebih banyak perpustakaan sumber terbuka ke dalam kami; program.

Kesukaran yang dihadapi dalam menggabungkan dua bahasa pengaturcaraan

Pertama, adalah perlu untuk menentukan bagaimana dua atau lebih aplikasi boleh berkomunikasi antara satu sama lain.

Sebagai contoh, menggunakan pustaka go-php Alex Palaestras, perkongsian memori antara proses PHP dan Go (seperti mod_php dalam Apache) boleh dicapai. Tetapi kefungsian perpustakaan ini mengehadkan penggunaan kami untuk menyelesaikan masalah.

Kami memutuskan untuk menggunakan satu lagi pendekatan yang lebih biasa: menstruktur interaksi antara proses dengan menggunakan soket /talian paip. Pendekatan ini telah membuktikan kebolehpercayaannya sepanjang dekad yang lalu dan dioptimumkan dengan baik pada peringkat sistem pengendalian.

Mula-mula, kami mencipta protokol binari mudah untuk bertukar-tukar data antara proses dan mengendalikan ralat penghantaran. Dalam bentuk yang paling mudah, jenis protokol ini menyerupai netrentetan dengan pengepala paket bersaiz tetap (17 bait dalam contoh kami), di mana Maklumat yang terkandung ialah jenis paket, saiz dan topeng binarinya maklumat, digunakan untuk menyemak integriti data.

Di bahagian PHP, kami menggunakan

fungsi pek, dan di sebelah Go, kami menggunakan pustaka pengekodan/perduaan.

Terdapat protokol yang agak ketinggalan zaman untuk kami dan kami telah menambah keupayaan untuk memanggil perkhidmatan net /rpc Go

terus daripada PHP. Ciri ini banyak membantu kami dalam pembangunan kemudian kerana kami boleh dengan mudah menyepadukan perpustakaan Go ke dalam aplikasi PHP. Hasil kerja ini boleh dilihat dalam satu lagi produk sumber terbuka kami Goridge .

Agihkan tugas di kalangan berbilang Pekerja PHP

Selepas mekanisme interaksi dilaksanakan, kami mula memikirkan cara untuk memindahkan tugas dengan lebih baik kepada proses PHP. Apabila tugas tiba, pelayan aplikasi mesti memilih pekerja terbiar untuk melaksanakannya. Jika proses pekerja ditamatkan dengan ralat atau "mati", kami mengosongkannya dan mencipta yang baharu. Jika proses pekerja berjaya dilaksanakan, kami mengembalikannya ke kumpulan pekerja di mana ia boleh digunakan untuk melaksanakan tugas.

Dilahirkan untuk kelajuan: gabungan PHP dan Golang - RoadRunnerUntuk menyimpan kumpulan proses pekerja aktif, kami menggunakan

saluran penimbal

Untuk mengosongkan proses pekerja "mati" yang tidak dijangka daripada kumpulan, kami Menambah mekanisme untuk mengesan ralat dan status proses pekerja. Akhir sekali, kami mempunyai pelayan PHP yang berfungsi yang mampu mengendalikan sebarang permintaan yang diberikan dalam bentuk binari.

Untuk membolehkan aplikasi kami mula berfungsi sebagai pelayan web, kami mesti memilih standard PHP yang boleh dipercayai untuk mengendalikan sebarang permintaan HTTP yang masuk. Dalam kes kami, kami hanya menukar permintaan net/http mudah daripada Go

kepada format PSR-7 supaya ia serasi dengan kebanyakan rangka kerja PHP yang tersedia hari ini . Memandangkan PSR-7 dianggap tidak berubah (ada yang mengatakan secara teknikalnya tidak), pembangun mesti menulis aplikasi yang pada dasarnya tidak menganggap permintaan sebagai entiti global. Ini selaras sepenuhnya dengan konsep proses pemastautin PHP. Pelaksanaan akhir kami (yang belum menerima nama lagi) kelihatan seperti ini:

RoadRunner - Tinggi - Prestasi Pelayan Aplikasi PHP

Tugas ujian pertama kami ialah bahagian belakang API di mana kami akan mengalami letusan permintaan yang tidak dapat diramalkan secara berkala (lebih kerap daripada biasa). Walaupun keupayaan nginx mencukupi dalam kebanyakan kes, kami sering menghadapi ralat 502 disebabkan oleh ketidakupayaan untuk mengimbangi sistem dengan cepat di bawah peningkatan beban yang dijangkakan.

Untuk menyelesaikan masalah ini, kami menggunakan pelayan aplikasi PHP/Go pertama kami pada awal 2018. Dan mencapai hasil yang menakjubkan serta-merta! Kami bukan sahaja menghapuskan ralat 502 sepenuhnya, kami juga mengurangkan bilangan pelayan sebanyak dua pertiga, menjimatkan banyak wang dan menyelesaikan masalah yang menyakitkan bagi jurutera dan pengurus produk.

Pada pertengahan tahun, kami menambah baik penyelesaian kami dan mengeluarkannya di GitHub di bawah lesen MIT dan menamakannya RoadRunner, sekali gus menekankan kelajuan dan kecekapannya yang menakjubkan.

Cara RoadRunner meningkatkan timbunan pembangunan anda

Penggunaan RoadRunner membolehkan kami menggunakan jaring perisian tengah/http di sebelah Go, walaupun dalam Pengesahan JWT sebelum permintaan masuk ke PHP, serta mengendalikan WebSocket dan keadaan agregat global dalam Prometheus.

Terima kasih kepada RPC terbina dalam, anda boleh membuka API mana-mana pustaka Go dalam PHP tanpa menulis pakej sambungan. Lebih-lebih lagi, dengan RoadRunner, anda boleh menggunakan pelayan baharu yang berbeza daripada HTTP. Contohnya termasuk menjalankan pemproses AWS Lambda dalam PHP, mencipta baris gilir pemilih yang berkuasa, dan juga menambahkan gRPC pada aplikasi kami.

Menggunakan kedua-dua PHP dan Go, penyelesaiannya telah dipertingkatkan secara berterusan, meningkatkan prestasi aplikasi sebanyak 40x dalam beberapa ujian, menambah baik alatan penyahpepijatan, membolehkan penyepaduan dengan rangka kerja Symfony dan menambah Sokongan untuk HTTPS, HTTP/2, pemalam dan PSR-17.

Kesimpulan

Sesetengah orang masih terikat dengan konsep PHP yang lapuk, menganggap PHP adalah bahasa yang perlahan dan menyusahkan hanya sesuai untuk menulis pemalam di bawah WordPress. Orang-orang ini bahkan mengatakan bahawa PHP mempunyai had: apabila aplikasi menjadi cukup besar, anda perlu memilih bahasa yang lebih "matang" dan menulis semula pangkalan kod yang terkumpul selama ini.

Jawapan saya kepada soalan ini ialah: fikir semula. Kami percaya anda sahaja yang telah menetapkan beberapa had pada PHP. Anda boleh menghabiskan hidup anda berpindah dari satu bahasa ke bahasa lain, cuba mencari bahasa yang sesuai dengan keperluan anda, atau anda boleh menganggap bahasa sebagai alat. Dengan bahasa seperti PHP, kelemahan yang sepatutnya mungkin menjadi sebab sebenar kejayaannya. Jika anda menggabungkannya dengan bahasa lain seperti Go, anda mencipta produk yang lebih berkuasa daripada hanya menggunakan satu bahasa.

Selepas menggunakan Go dan PHP secara bergantian, kita boleh mengatakan bahawa kita menyukainya. Kami tidak akan mengorbankan satu untuk yang lain sebaliknya, kami akan mencari cara untuk mendapatkan lebih banyak daripada seni bina dua ini.

Alamat asal bahasa Inggeris: https://sudonull.com/post/6470-RoadRunner-PHP-is-not-created-to-die-or-Golang-to-the-rescue

Alamat terjemahan: https://learnku.com/php/t/61733

Pembelajaran yang disyorkan: "Tutorial Video PHP"

Atas ialah kandungan terperinci Dilahirkan untuk kelajuan: gabungan PHP dan Golang - RoadRunner. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:learnku.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam