RoadRunner: PHP o'lish uchun yoki Golang qutqarish uchun yaratilgan emas

RoadRunner: PHP o'lish uchun yoki Golang qutqarish uchun yaratilgan emas

Salom, Xabr! Biz Badoo'da faolmiz PHP ishlashi ustida ishlash, chunki bizda bu tilda juda katta tizim mavjud va ishlash masalasi pulni tejash masalasidir. O'n yildan ko'proq vaqt oldin biz buning uchun PHP-FPM ni yaratdik, u dastlab PHP uchun yamoqlar to'plami edi, keyin esa rasmiy tarqatishning bir qismiga aylandi.

So'nggi yillarda PHP katta yutuqlarga erishdi: axlat yig'uvchisi yaxshilandi, barqarorlik darajasi oshdi - bugungi kunda PHPda hech qanday muammosiz demonlar va uzoq muddatli skriptlarni yozishingiz mumkin. Bu Spiral Scout-ga oldinga borish imkonini berdi: RoadRunner, PHP-FPMdan farqli o'laroq, so'rovlar o'rtasida xotirani tozalamaydi, bu esa qo'shimcha ishlash afzalliklarini beradi (garchi bu yondashuv ishlab chiqish jarayonini murakkablashtirsa ham). Biz hozirda ushbu vosita bilan tajriba o‘tkazmoqdamiz, ammo bizda hali baham ko‘radigan natijalar yo‘q. Ularni kutish yanada qiziqarli bo'lishi uchun, Biz Spiral Scout-dan RoadRunner e'lonining tarjimasini nashr etmoqdamiz.

Maqolaning yondashuvi bizga yaqin: muammolarimizni hal qilishda biz ko'pincha PHP va Go kombinatsiyasidan foydalanamiz, ikkala tilning afzalliklaridan foydalanamiz va biridan ikkinchisining foydasiga voz kechmaymiz.

Enjoy!

So'nggi o'n yil ichida biz ro'yxatdagi kompaniyalar uchun ilovalar yaratdik Fortune 500, va 500 dan ortiq foydalanuvchi auditoriyasi bo'lmagan korxonalar uchun. Bu vaqt davomida bizning muhandislarimiz asosan PHP-da backend-ni ishlab chiqdilar. Ammo ikki yil oldin nimadir nafaqat mahsulotlarimiz unumdorligiga, balki ularning kengaytirilishiga ham katta ta'sir ko'rsatdi - biz Golang (Go) ni texnologik stekimizga kiritdik.

Deyarli darhol biz Go bizga 40 baravar tezroq ishlashga ega bo'lgan kattaroq ilovalarni yaratishga imkon berganligini aniqladik. Uning yordamida biz PHP-da yozilgan mavjud mahsulotlarni kengaytira oldik, ularni ikkala tilning afzalliklarini birlashtirgan holda yaxshiladik.

Biz sizga Go va PHP kombinatsiyasi qanday qilib haqiqiy rivojlanish muammolarini hal qilishda yordam berishini va u qanday qilib biz uchun ba'zi muammolarni bartaraf eta oladigan vositaga aylanganini aytib beramiz. PHP o'layotgan model.

Sizning kundalik PHP ishlab chiqish muhitingiz

PHP ning nobud bo'lgan modelini jonlantirish uchun Go dan qanday foydalanish haqida gapirishdan oldin, keling, standart PHP ishlab chiqish muhitingizni ko'rib chiqaylik.

Aksariyat hollarda siz dasturni nginx veb-server va PHP-FPM serveri kombinatsiyasidan foydalanib ishga tushirasiz. Birinchisi statik fayllarga xizmat qiladi va maxsus so'rovlarni PHP-FPM ga yo'naltiradi va PHP-FPM o'zi PHP kodini bajaradi. Ehtimol, siz Apache va mod_php-dan kamroq mashhur kombinatsiyadan foydalanayotgandirsiz. Ammo u biroz boshqacha ishlayotgan bo'lsa-da, printsiplar bir xil.

PHP-FPM dastur kodini qanday bajarishini ko'rib chiqamiz. So'rov kelganda, PHP-FPM PHP bola jarayonini ishga tushiradi va so'rov ma'lumotlarini uning holatining bir qismi sifatida uzatadi (_GET, _POST, _SERVER va boshqalar).

PHP skriptini bajarish jarayonida holat o'zgarmaydi, shuning uchun kirish ma'lumotlarining yangi to'plamini olishning faqat bitta usuli bor: jarayon xotirasini tozalash va uni qayta ishga tushirish.

Ushbu ijro modeli juda ko'p afzalliklarga ega. Xotirani sarflash haqida ko'p tashvishlanishingiz shart emas, barcha jarayonlar butunlay izolyatsiya qilingan va agar ulardan biri o'lsa, qolgan jarayonlarga ta'sir qilmasdan avtomatik ravishda qayta yaratiladi. Ammo bu yondashuv dasturni kengaytirishga urinayotganda paydo bo'ladigan kamchiliklarga ham ega.

Oddiy PHP muhitining kamchiliklari va samarasizligi

Agar siz PHPda professional rivojlanish bilan shug'ullansangiz, unda siz yangi loyihani qaerdan boshlashni bilasiz - ramka tanlash orqali. U qaramlik kiritish uchun kutubxonalar, ORMlar, tarjimalar va shablonlardan iborat. Va, albatta, barcha foydalanuvchi ma'lumotlarini bir ob'ektga qulay tarzda joylashtirish mumkin (Symfony/HttpFoundation yoki PSR-7). Ramkalar ajoyib!

Lekin hamma narsaning o'z narxi bor. Har qanday korporativ darajadagi tizimda oddiy foydalanuvchi so'rovini qayta ishlash yoki ma'lumotlar bazasiga kirish uchun siz kamida o'nlab fayllarni yuklashingiz, ko'plab sinflarni yaratishingiz va bir nechta konfiguratsiyalarni tahlil qilishingiz kerak bo'ladi. Ammo eng yomoni shundaki, har bir vazifani bajarganingizdan so'ng siz hamma narsani qayta o'rnatishingiz va qaytadan boshlashingiz kerak bo'ladi: siz boshlagan barcha kodlar foydasiz bo'lib qoladi, uning yordami bilan siz boshqa so'rovni qayta ishlamaysiz. Buni boshqa tilda yozadigan har qanday dasturchiga ayting, shunda uning yuzida dovdirab qolasiz.

PHP muhandislari ko'p yillar davomida aqlli dangasa yuklash texnikasi, mikroframeworklar, optimallashtirilgan kutubxonalar, keshlar va hokazolardan foydalanib, bu muammoni hal qilish yo'llarini izlashdi. Lekin oxir-oqibat, siz hali ham butun dasturni qayta o'rnatishingiz va qayta-qayta boshlashingiz kerak. (Tarjimonning eslatmasi: bu muammoning paydo bo'lishi bilan qisman hal qilinadi preload PHP 7.4 da)

Go bilan PHP bir nechta so'rovlarga bardosh bera oladimi?

Bir necha daqiqadan ko'proq (soat yoki kungacha) davom etadigan PHP skriptlarini yozish mumkin: masalan, cron vazifalari, CSV parserlari, navbatni buzuvchilar. Ularning barchasi bir xil stsenariy bo'yicha ishlaydi: ular vazifani oladilar, uni bajaradilar va keyingisini kutadilar. Kod xotirada joylashgan bo'lib, qimmatbaho millisekundlarni tejaydi, chunki ramka va dasturni yuklash uchun ko'plab qo'shimcha qadamlar talab qilinadi.

Ammo uzoq muddatli skriptlarni ishlab chiqish unchalik oson emas. Har qanday xato jarayonni butunlay o'ldiradi, xotiraning oqishini tashxislash sizni aqldan ozdiradi va siz endi F5 disk raskadrovkadan foydalana olmaysiz.

PHP 7-ning chiqarilishi bilan vaziyat yaxshilandi: ishonchli axlat yig'uvchi paydo bo'ldi, xatolarni hal qilish osonroq bo'ldi va yadro kengaytmalari endi sizib chiqishdan himoyalangan. To'g'ri, muhandislar hali ham xotiraga ehtiyot bo'lishlari va koddagi davlat muammolaridan xabardor bo'lishlari kerak (bu narsalar haqida qayg'urmasligimiz kerak bo'lgan til bormi?). Va shunga qaramay, PHP 7 da bizni kamroq kutilmagan hodisalar kutmoqda.

Uzoq muddatli PHP skriptlari bilan ishlash modelini olish, uni HTTP so'rovlarini qayta ishlash kabi ahamiyatsizroq vazifalarga moslashtirish va shu bilan har bir so'rov uchun hamma narsani noldan yuklash zaruratini bartaraf etish mumkinmi?

Ushbu muammoni hal qilish uchun biz birinchi navbatda HTTP so'rovlarini qabul qila oladigan va ularni har safar o'ldirmasdan PHP ishchisiga birma-bir yo'naltira oladigan server dasturini joriy qilishimiz kerak edi.

Biz veb-serverni sof PHP (PHP-PM) da yoki C kengaytmasidan (Swoole) foydalanib yozishimiz mumkinligini bilardik. Va har bir usulning o'ziga xos afzalliklari bo'lsa-da, ikkala variant ham bizga mos kelmadi - biz ko'proq narsani xohladik. Bizga shunchaki veb-serverdan ko'ra ko'proq narsa kerak edi - biz PHP-dagi "qattiq start" bilan bog'liq muammolardan xalos bo'lishi mumkin bo'lgan yechimga ega bo'lishni umid qildik, bu esa bir vaqtning o'zida aniq ilovalar uchun osongina moslashtirilishi va kengaytirilishi mumkin. Ya'ni bizga dastur serveri kerak edi.

Go bu borada yordam bera oladimi? Biz buni bilardik, chunki til ilovalarni bitta ikkiliklarga kompilyatsiya qiladi; u o'zaro platformalardir; HTTP bilan ishlash uchun o'zining, juda oqlangan, parallel ishlov berish modeli (parallellik) va kutubxonasidan foydalanadi; va nihoyat, minglab ochiq manbali kutubxonalar va integratsiya biz uchun mavjud bo'ladi.

Ikki dasturlash tilini birlashtirishdagi qiyinchiliklar

Birinchi qadam ikki yoki undan ortiq ilovalar bir-biri bilan qanday bog'lanishini aniqlash edi.

Masalan, foydalanish ajoyib kutubxona Aleks Palaestras PHP va Go jarayonlari o'rtasida xotira almashishni amalga oshirishi mumkin (Apache'dagi mod_php ga o'xshash). Ammo bu kutubxonada muammoni hal qilishda foydalanishni cheklaydigan xususiyatlar mavjud.

Biz yana bir keng tarqalgan yondashuvdan foydalanishga qaror qildik: jarayonlar o'rtasida rozetkalar/quvurlar orqali o'zaro aloqani o'rnatish. Ushbu yondashuv so'nggi o'n yilliklarda o'zining ishonchliligini isbotladi va operatsion tizim darajasida yaxshi optimallashtirilgan.

Boshlash uchun biz jarayonlar o'rtasida ma'lumot almashish va uzatish xatolarini qayta ishlash uchun oddiy ikkilik protokolni yaratdik. Eng oddiy shaklda ushbu turdagi protokol o'xshash netstring с belgilangan o'lchamdagi paket sarlavhasi (bizning holatda 17 bayt), unda paket turi, uning o'lchami va ma'lumotlar yaxlitligini tekshirish uchun ikkilik niqob haqida ma'lumot mavjud.

PHP tomonida biz foydalandik paket funktsiyasi, va borish tomonida - kutubxona kodlash/ikkilik.

Bizga bitta protokol etarli emasdek tuyuldi - shuning uchun biz qo'ng'iroq qilish imkoniyatini qo'shdik Net/rpc xizmatlariga to'g'ridan-to'g'ri PHP dan o'ting. Keyinchalik bu bizga rivojlanishda katta yordam berdi, chunki biz Go kutubxonalarini PHP ilovalariga osongina integratsiyalashimiz mumkin edi. Ushbu ishning natijasini, masalan, bizning boshqa ochiq kodli mahsulotimizda ko'rish mumkin Gorij.

Vazifalarni bir nechta PHP ishchilariga taqsimlash

O'zaro ta'sir mexanizmini amalga oshirganimizdan so'ng, biz vazifalarni PHP jarayonlariga qanday qilib eng samarali tarzda o'tkazish haqida o'ylay boshladik. Vazifa kelganda, dastur serveri uni bajarish uchun bepul ishchini tanlashi kerak. Agar ishchi/jarayon xato bilan yakunlansa yoki "o'lib qolsa", biz undan qutulamiz va uning o'rniga yangisini yaratamiz. Va agar ishchi/jarayon muvaffaqiyatli yakunlangan bo'lsa, biz uni vazifalarni bajarish uchun mavjud bo'lgan ishchilar puliga qaytaramiz.

RoadRunner: PHP o'lish uchun yoki Golang qutqarish uchun yaratilgan emas

Biz foydalangan faol ishchilar hovuzini saqlash uchun buferlangan kanal, kutilmaganda "o'lik" ishchilarni hovuzdan olib tashlash uchun biz xatolar va ishchi holatlarini kuzatish mexanizmini qo'shdik.

Natijada, biz ikkilik shaklda taqdim etilgan har qanday so'rovlarni qayta ishlashga qodir ishlaydigan PHP serverini oldik.

Ilovamiz veb-server sifatida ishlashi uchun biz har qanday kiruvchi HTTP so'rovlarini ifodalash uchun ishonchli PHP standartini tanlashimiz kerak edi. Bizning holatlarimizda biz shunchaki aylantirish formatga o'tishdan net/http so'rovi PSR-7shuning uchun u bugungi kunda mavjud bo'lgan ko'pgina PHP ramkalar bilan mos keladi.

PSR-7 o'zgarmas deb hisoblanganligi sababli (ba'zilar texnik jihatdan bunday emas deb aytishadi), ishlab chiquvchilar so'rovni global ob'ekt sifatida ko'rib chiqmaydigan ilovalarni yozishlari kerak. Bu uzoq muddatli PHP jarayonlari kontseptsiyasiga juda mos keladi. Hali nomlanmagan yakuniy dasturimiz quyidagicha ko'rinish oldi:

RoadRunner: PHP o'lish uchun yoki Golang qutqarish uchun yaratilgan emas

RoadRunner bilan tanishtirish - yuqori samarali PHP dastur serveri

Bizning birinchi sinov vazifamiz vaqti-vaqti bilan kutilmagan so'rovlarni boshdan kechiradigan (odatdagidan ham tez-tez) API backend edi. Ko'p hollarda nginx etarli bo'lsa-da, biz muntazam ravishda 502 xatoga duch keldik, chunki biz tizimni yukning kutilgan o'sishi uchun etarlicha tez muvozanatlashtira olmadik.

Ushbu yechimni almashtirish uchun biz 2018-yil boshida birinchi PHP/Go dastur serverimizni ishga tushirdik. Va darhol biz ajoyib ta'sirga ega bo'ldik! Biz nafaqat 502 xatosidan butunlay xalos bo‘ldik, balki serverlar sonini uchdan ikkiga qisqartirishga muvaffaq bo‘ldik, muhandislar va mahsulot menejerlari uchun ko‘p pul va bosh og‘riqni tejadik.

Yil o'rtalarida biz o'z yechimimizni takomillashtirdik, uni MIT litsenziyasi ostida GitHub-da nashr qildik va uni chaqirdik. Roadrunner, shu bilan uning ajoyib tezligi va samaradorligini ta'kidlaydi.

RoadRunner qanday qilib sizning ishlab chiqish stekingizni yaxshilashi mumkin

ariza Roadrunner bizga Middleware net/http-dan o'tish tomonida so'rov PHP-ga tushmasdan oldin JWT tekshiruvini amalga oshirish, shuningdek Prometeyda WebSockets va global holatni yig'ish uchun foydalanish imkonini berdi.

O'rnatilgan RPC tufayli siz PHP uchun har qanday Go kutubxonalarining API-ni kengaytmalarni yozmasdan ochishingiz mumkin. Eng muhimi, RoadRunner-dan yangi HTTP bo'lmagan serverlarni joylashtirish uchun foydalanish mumkin. Masalan, PHP da ishga tushiruvchi ishlov beruvchilar AWS Lambda, ishonchli navbat busterlarini yaratish va hatto qo'shish gRPC ilovalarimizga.

PHP va Go hamjamiyatlari yordamida biz yechim barqarorligini oshirdik, baʼzi testlarda ilova unumdorligini 40 barobarga oshirdik, disk raskadrovka vositalarini yaxshiladik, Symfony framework bilan integratsiyani amalga oshirdik va HTTPS, HTTP/ qoʻllab-quvvatlashini qoʻshdik. 2, plaginlar va PSR-17.

xulosa

Ba'zi odamlar hali ham PHP ning eskirgan ko'rinishida sekin, noqulay til sifatida faqat WordPress plaginlarini yozish uchun mos keladi. Bu odamlar hatto PHP-da cheklov borligini aytishlari mumkin: dastur etarlicha kattalashganda, siz ko'proq "etuk" tilni tanlashingiz va ko'p yillar davomida to'plangan kod bazasini qayta yozishingiz kerak.

Bularning barchasiga men javob bermoqchiman: yana o'ylab ko'ring. PHP uchun har qanday cheklovlarni faqat siz o'rnatishingiz mumkinligiga ishonamiz. Siz butun hayotingizni bir tildan ikkinchisiga sakrab o'tishingiz, ehtiyojlaringiz uchun mukammal moslikni topishga harakat qilishingiz yoki tillarni vosita sifatida o'ylashni boshlashingiz mumkin. PHP kabi tilning kamchiliklari uning muvaffaqiyatining sabablari bo'lishi mumkin. Va agar siz uni Go kabi boshqa til bilan birlashtirsangiz, faqat bitta til bilan chegaralanganingizdan ko'ra ancha kuchli mahsulotlar yaratishingiz mumkin.

Go va PHP kombinatsiyasi bilan ishlaganimizdan so'ng, biz ularni yaxshi ko'rishimizni aytishimiz mumkin. Biz bir-birimizni qurbon qilishni rejalashtirmayapmiz, aksincha, ushbu dual stackdan yanada ko'proq qiymat olish yo'llarini qidiramiz.

UPD: Biz RoadRunner yaratuvchisini va asl maqolaning hammuallifini tabriklaymiz - Lachesis

Manba: www.habr.com

a Izoh qo'shish