RoadRunner: PHP ei ole loodud surema, vÔi Golang prÔksib appi

RoadRunner: PHP ei ole loodud surema, vÔi Golang prÔksib appi

Tere, Habr! Me Badoo-s töötame aktiivselt PHP jĂ”udluse kallal, kuna meil on piisavalt suur sĂŒsteem sellel keelel ja jĂ”udluse kĂŒsimus on rahakĂŒsimus. Üle kĂŒmne aasta tagasi lĂ”ime selle jaoks PHP-FPM, mis algselt oli PHP jaoks patĆĄide kogum ja hiljem sai ametlikuks osaks.

Viimastel aastatel on PHP oluliselt edasi arenenud: prĂŒgikorjaja on paranenud, stabiilsus on kasvanud - tĂ€na on PHP-s vĂ”imalik probleemideta kirjutada deemonid ja pikaealisi skripte. See vĂ”imaldas Spiral Scoutil minna kaugemale: RoadRunner ei puhasta, erinevalt PHP-FPM-ist, mĂ€lu pĂ€ringute vahel, mis annab lisavĂ”idu jĂ”udluses (kuigi see lĂ€henemine muudab arendamise protsessi keerulisemaks). Praegu katsetame seda tööriista, kuid meil pole veel tulemusi, millega jagada. Et oodata oleks lĂ”busam, publitseerime Spiral Scouti RoadRunneri teadet tĂ”lke.

Artiklis esitatud lĂ€henemine on meile tuttav: oma probleemide lahendamisel kasutame ka enamasti PHP ja Go kombinatsiooni, saades kasu mĂ”lema keele eeliste kasutamisest ja loobumata ĂŒhest teise kasuks.

Naudi!

Viimase kĂŒmne aasta jooksul oleme loonud rakendusi nii ettevĂ”tetele, kes kuuluvad nimekirja Fortune 500, kui ka Ă€ridele, millel on maksimaalselt 500 kasutajat. Kogu selle aja jooksul on meie insenerid arendanud peamiselt PHP-l baseeruvat taustsĂŒsteemi. Ent kaks aastat tagasi mĂ”jutas ĂŒks asi pĂ”hjalikult mitte ainult meie toodete sooritust, vaid ka nende skaleeritavust — lisasime oma tehnoloogiahunnikusse Golangi (Go).

Peaaegu kohe avastasime, et Go vÔimaldab meil luua suuremaid rakendusi, saavutades kuni 40-kordse tootlikkuse kasvu. Selle abil suutsime laiendada olemasolevaid PHP-s kirjutatud tooteid, parandades neid, kasutades kahe keele eeliste kombinatsiooni.

RÀÀgime, kuidas Go ja PHP kombinatsioon aitab lahendada reaalmaailma arendusprobleeme ning kuidas see on muutunud meie jaoks tööriistaks, mis suudab lahendada osa probleemidest, millega seostatakse PHP 'suremise' mudelit.

Teie igapÀevane PHP arenduskeskkond

Enne kui rÀÀgime, kuidas Go abil PHP 'suremise' mudelit ellu Àratada, vaatame teie tavalist PHP arenduskeskkonda.

Enamikul juhtudel kÀitate rakendust koos veebiserveri nginx ja PHP-FPM serveriga. Esimene teenindab staatilisi faile ja suunab PHP-FPM-i spetsiifilised pÀringud, samas kui PHP-FPM tÀidab PHP-koodi. VÔib-olla kasutate vÀhem populaarset kombinatsiooni Apache ja mod_php. Kuid kuigi selle toimimine on veidi erinev, on pÔhimÔtted samad.

Uurime, kuidas PHP-FPM rakenduskoodi tĂ€idab. Kui pĂ€ring saabub, alustab PHP-FPM alamsĂŒsteemi PHP-protsessi ning edastab pĂ€ringu ĂŒksikasjad osana selle olekust (_GET, _POST, _SERVER jne).

Olek ei saa PHP-skripti tĂ€itmise ajal muutuda, seega saab uue sisendi ainult ĂŒhe viisiga: protsessi mĂ€lu puhastades ja selle uuesti initsialiseerides.

Sellise tĂ€itmismudelil on palju eeliseid. Te ei pea muretsema mĂ€lutarbimise pĂ€rast, kĂ”ik protsessid on tĂ€ielikult isoleeritud ja kui ĂŒks neist 'sureb', siis luuakse see automaatselt uuesti ning see ei mĂ”juta teisi protsesse. Kuid sellel lĂ€henemisel on ka puudusi, mis ilmnevad rakenduse skaleerimise katsetel.

Tavalise PHP-keskkonna puudused ja tÔhususe puudumine

Kui te tegelete professionaalse PHP arendamisega, siis teate, et uue projekti alustamine algab raamistikku valimisest. See koosneb teekidest sĂ”ltuvuste sĂŒstimiseks, ORM-idest, tĂ”lgetest ja mallidest. Muidugi saab kĂ”ik sisendid mugavalt paigutada ĂŒhe objekti sisse (Symfony/HttpFoundation vĂ”i PSR-7). Raamistiku kasutamine on Ă€ge!

Kuid kĂ”igel on oma hind. Igasse ettevĂ”tte taseme raamistikku lihtsa kasutaja pĂ€ringu vĂ”i andmebaasi pĂ€ringu töötlemiseks tuleb laadida vĂ€hemalt kĂŒmneid faile, luua mitmeid klasse ja analĂŒĂŒsida mitmeid konfiguratsioone. Veelgi halvem on see, et iga ĂŒlesande tĂ€itmise jĂ€rel tuleb kĂ”ik taastada ja alustada nullist: kogu just kĂ€ivitatud kood muutub kasutuks, te ei saa sellega enam ĂŒhtki pĂ€ringut töödelda. RÀÀkige sellest igale programmeerijale, kes kirjutab mĂ”nes teises keeles, ja nĂ€ete hĂ€mmeldust tema nĂ€ol.

PHP-arendajad on aastaid otsinud viise selle probleemi lahendamiseks, kasutades hoolikalt vĂ€lja töötatud „laiskade” laadimise meetodeid, mikroraamistikke, optimeeritud raamatukogusid, vahemĂ€lu jne. LĂ”puks peab aga ikkagi kogu rakenduse nullima ja alustama uuesti, ja uuesti. (TĂ”lkija mĂ€rkus: osaliselt lahendab seda probleemi preload PHP 7.4 tulek)

Kas PHP suudab Go abil taluda rohkem kui ĂŒhte pĂ€ringut?

On vĂ”imalik kirjutada PHP-skripte, mis kestavad kauem kui paar minutit (kuni tundide vĂ”i pĂ€evadeni): nĂ€iteks cron-ĂŒlesanded, CSV-parsirid, jĂ€rjekorraanalĂŒsaatorid. KĂ”ik need töötavad ĂŒhes stsenaariumis: nad vĂ”tavad ĂŒlesande, tĂ€idavad selle, ootavad jĂ€rgmist. Kood on pidevalt mĂ€lus, sÀÀstes hinnalisi millisekundeid, kuna raamistikku ja rakendust laadides tuleb teha mitmeid tĂ€iendavaid toiminguid.

Kuid pikaajaliste skriptide arendamine ei ole nii lihtne. Iga viga tapab protsessi tÀielikult, mÀlulekete tÔrkeotsing ajab hulluks ja F5 abil silumise kasutamine ei ole enam vÔimalik.

PHP 7 vĂ€ljumisega on olukord paranenud: ilmus usaldusvÀÀrne prĂŒgikorjaja, vigade töötlemine on lihtsam ja tuumapikendused on nĂŒĂŒd lekete eest kaitstud. Siiski peavad insenerid endiselt olema ettevaatlikud mĂ€luga ja meeles pidama koodi seisundi probleeme (kas on olemas keel, kus nendele asjadele ei pea tĂ€helepanu pöörama?). Siiski on PHP 7-s meid vĂ€hem ĂŒllatusi ootamas.

Kas on vÔimalik vÔtta pikaajaliste PHP-skriptide töömudel, kohandada seda lihtsate HTTP-pÀringute töötlemiseks ja seelÀbi vabaneda vajadusest iga pÀringu puhul kÔik uuesti laadida?

Selle ĂŒlesande lahendamiseks oli esmalt vaja rakendada serveri rakendus, mis suudaks vastu vĂ”tta HTTP-pĂ€ringuid ja suunata need jĂ€rjestikku PHP-töörakendusele, tappa seda igal korral mitte.

Me teadsime, et suudame kirjutada veebiserveri puhta PHP (PHP-PM) vĂ”i C-laienduse (Swoole) abil. Kuigi mĂ”lemal meetodil on oma eelised, ei rahuldanud need meid – otsisime midagi enamat. Me vajasime mitte lihtsalt veebiserverit, vaid lahendust, mis suudaks meid vabastada PHP „raske kĂ€ivitamise” probleemidest ja mille saaks hĂ”lpsasti kohandada ja laiendada konkreetsete rakenduste jaoks. See tĂ€hendab, et vajasime rakendusserverit.

Kas Go saab meid aidata? Me teadisime, et saab, sest see keel kompileerib rakendused ĂŒksikutesse binaarfailidesse; see on platvormideĂŒlene; kasutab oma vĂ€ga elegantset, paralleelse töötlemise (concurrency) mudelit ja HTTP-töötlusraamatukogusid; ja lĂ”puks on meil ligipÀÀs tuhandetele avatud lĂ€htekoodiga raamatukogudele ja integratsioonidele.

Kaks programmeerimiskeelt ĂŒhendamise raskused

Esiteks pidi mÀÀrama, kuidas kaks vÔi enam rakendust omavahel suhtlevad.

NĂ€iteks kauni raamatukogu kaudu ilusa raamatukoguga Aleksa Palaestrasa vĂ”imaldas PHP ja Go protsesside vahel jagada mĂ€lu (sarnaselt mod_php-ga Apache'is). Kuid sellel teegil on omad eripĂ€rad, mis piiravad selle rakendamist meie ĂŒlesande lahendamiseks.

Otsustasime kasutada teistsugust, laialdasemalt levinud lĂ€henemist: ehitada protsesside vaheline suhtlus socket'ite/pĂ”hjal. See lĂ€henemine on viimase paarikĂŒmne aasta jooksul tĂ”estanud oma usaldusvÀÀrsust ning on operatsioonisĂŒsteemi tasandil hĂ€sti optimeeritud.

Alguses loodi lihtne binaarprotokoll andmete vahetamiseks protsesside vahel ja edastuse tĂ”rke kĂ€sitlemiseks. Selle lihtsaimas vormis on selline protokoll sarnane netstring koos fikseeritud suurusega pĂ€isega (meie juhul 17 baiti), mis sisaldab teavet paketi tĂŒĂŒbi, suuruse ja andmete terviklikkuse kontrollimiseks mĂ”eldud binaarsemaskide kohta.

PHP poolel kasutasime funktsiooni pack, ning Go poolel - raamatukogu encoding/binary.

Üks protokoll ei olnud piisav - ja lisasime vĂ”imaluse kutsuda Go teenuseid net/rpc otse PHP-st. Hiljem aitas see meid arenduses vĂ€ga, kuna saime hĂ”lpsasti integreerida Go teeke PHP rakendustesse. Selle töö tulemust saab nĂ€ha nĂ€iteks meie teises open-source tootmis. Goridge.

Ülesannete jaotamine mitmete PHP töötajate vahel

PĂ€rast suhtlemismehhanismi rakendamist hakkasime mĂ”tlema, kuidas kĂ”ige tĂ”husamalt edastada ĂŒlesandeid PHP protsessidele. Kui ĂŒlesanne saabub, peab rakendusserver valima selle tĂ€itmiseks vaba töötaja. Kui töötaja/protsess lĂ”petab töö vea tĂ”ttu vĂ”i «sureb», then eemaldame selle ja loome asemele uue. Kui töötaja/protsess töötab edukalt, tagastame selle ĂŒlesannete tĂ€itmiseks kergesti kĂ€tte saadavate töötajate hulka.

RoadRunner: PHP ei ole loodud surema, vÔi Golang prÔksib appi

Aktiveeritud töötajate kihi salvestamiseks kasutasime buffeeritud kanali, et ootamatult «surnud» töötajad eemaldada, lisasime töötajate vigade ja seisundite jÀlgimise mehhanismi.

Tulemuseks saime töötava PHP serveri, mis suudab kÀsitleda kÔiki binaarses vormingus esitatud pÀringuid.

Kuna meie rakendus peab töötama veebiserverina, pidime valima usaldusvÀÀrse PHP-standardi, et esindada kĂ”iki sissetulevaid HTTP-pĂ€ringuid. Meie puhul me lihtsalt muudame net/http-pĂ€ringu Go-s formaati PSR-7, et see oleks ĂŒhilduv enamikuga tĂ€napĂ€eval saadaval olevatest PHP-raamistikkudest.

Kuna PSR-7 on muudetav (mĂ”ned ĂŒtlevad, et tehniliselt see nii ei ole), peavad arendajad kirjutama rakendusi, mis ei kĂ€sitle pĂ€ringut globaalse olendina. See sobib suurepĂ€raselt pĂŒsivate PHP-protsesside kontseptsiooniga. Meie lĂ”plik teostus, millele pole veel nime antud, nĂ€gi vĂ€lja selline:

RoadRunner: PHP ei ole loodud surema, vÔi Golang prÔksib appi

Tutvustame RoadRunnerit — kĂ”rge jĂ”udlusega PHP-rakenduste server

Meie esimene testĂŒlesanne oli API tagaplaan, millel esines perioodiliselt ettearvamatu pĂ€ringute hĂŒppeid (kordades sagedamini kui tavaliselt). Kuigi enamikul juhtudel piisab nginx-i vĂ”imekusest, seisame pidevalt silmitsi 502. vea, kuna ei suutnud sĂŒsteemi piisavalt kiiresti tasakaalustada oodatava koormuse suurenemise tĂ”ttu.

2018. aasta alguses asendasime selle lahenduse, kasutades esmakordselt meie PHP/Go rakenduste serverit. Tulemused olid hÀmmastavad! Saime mitte ainult 502 tÔrkest lahti, vaid vÀhendasime ka teenuste arvu kahel kolmandikul, sÀÀstes sellega palju raha ja vÀhendades inseneride ja tootejuhtide peavalusid.

Aasta keskpaiku tÀiustasime meie lahendust, avaldasime selle GitHub'is MIT litsentsi alusel ja kutsusime seda RoadRunner, rÔhutades selle uskumatut kiirus ja efektiivsust.

Kuidas RoadRunner vÔib teie arenduslaari parandada

Kasutamine RoadRunner sai meie vÔimaluseks kasutada Middleware net/http Go poolel, et teostada JWT-verify enne, kui pÀring jÔuab PHP'ni, samuti WebSocketide töötlemiseks ja globaalseteks olekute kogumiseks Prometheuses.

Sisseehitatud RPC abil on vÔimalik avada API igasuguste Go raamatukogude jaoks PHP's ilma wrapper-ekstensioonide kirjutamiseta. Veelgi olulisem on see, et RoadRunner'i abil on vÔimalik juurutada uusi servereid, mis erinevad HTTP-st. NÀiteks on vÔimalik kÀivitada PHP töötlajaid AWS Lambda, luua usaldusvÀÀrseid jÀrjekorra parsereid ja isegi lisada gRPC meie rakendustesse.

PHP ja Go kogukondade toel oleme parandanud lahenduse stabiilsust, suurendanud testides rakenduste jÔudlust kuni 40 korda, tÀiustanud tÔrkeotsingu tööriistu, rakendanud integratsiooni Symfony raamistikuga ning lisanud toe HTTPS, HTTP/2, pistikprogrammidele ja PSR-17-le.

KokkuvÔte

MĂ”ned inimesed on endiselt kinni vananenud arusaamades PHP-st kui aeglasest ja mahukast keelest, mida kasutatakse ainult WordPressi pistikpluginate kirjutamiseks. Need inimesed vĂ”ivad isegi vĂ€ita, et PHP-l on selline piirang: kui rakendus muutub piisavalt suureks, tuleb valida „kĂŒpsem“ keel ja ĂŒmber kirjutada aastate jooksul kogunenud koodibaas.

KĂ”igele sellele tahaks vastata: mĂ”elge veel kord. Me usume, et ainult teie ise seate PHP-le mingid piirangud. VĂ”ite veeta kogu oma elu ĂŒhel keelelt teisele siirdumisel, pĂŒĂŒdes leida teie vajadustega ideaalset kombinatsiooni, vĂ”i vĂ”ite hakata keeli kĂ€sitlema kui tööriistu. PHP keele vĂ€idetavad puudused vĂ”ivad tegelikult olla selle edu pĂ”hjuseks. Ja kui kombineerida see mĂ”ne teise keelega, nagu Go, siis loote palju vĂ”imsamaid tooteid, kui kui piirdute ainult ĂŒhe keele kasutamisega.

Töötanud Go ja PHP kombinatsiooniga, saame kinnitada, et oleme neist armunud. Me ei plaani ĂŒhte teise arvelt ohverdada — vastupidi, otsime viise, kuidas veelgi rohkem kasu saada sellest kahekordsest tehnoloogiast.

UPD: tervitame RoadRunneri loojat ja originaalartikli kaasautorit — Lachezis

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster