RoadRunner: PHP ass net gebaut fir ze stierwen, oder Golang fir d'Rettung

RoadRunner: PHP ass net gebaut fir ze stierwen, oder Golang fir d'Rettung

Moien, Habr! Mir sinn aktiv bei Badoo schaffen op PHP Leeschtung, well mir an dëser Sprooch e relativ grousse System hunn an d'Fro vun der Leeschtung ass eng Saach vu Geld spueren. Viru méi wéi zéng Joer hu mir PHP-FPM fir dëst erstallt, wat am Ufank e Set vu Patches fir PHP war, a spéider Deel vun der offizieller Verdeelung gouf.

An de leschte Joeren huet PHP grouss Fortschrëtter gemaach: de Müllsammler huet sech verbessert, de Stabilitéitsniveau ass eropgaang - haut kënnt Dir Daemonen a laanglieweg Scripten an PHP ouni Probleemer schreiwen. Dëst erlaabt Spiral Scout weider ze goen: RoadRunner, am Géigesaz zu PHP-FPM, botzt d'Erënnerung net tëscht Ufroen, wat zousätzlech Leeschtungsvirdeeler bitt (obwuel dës Approche den Entwécklungsprozess komplizéiert). Mir experimentéiere momentan mat dësem Tool, awer mir hu nach keng Resultater fir ze deelen. Fir et méi Spaass ze maachen op si ze waarden, Mir publizéieren eng Iwwersetzung vun der RoadRunner Ukënnegung vum Spiral Scout.

D'Approche vum Artikel ass no bei eis: wann Dir eis Probleemer léist, benotze mir och meeschtens eng Kombinatioun vu PHP a Go, fir d'Virdeeler vu béide Sproochen ze kréien an net een zugonschte vun deem aneren opzeginn.

Genéisst!

An de leschten zéng Joer hu mir Uwendunge fir Firmen aus der Lëscht erstallt Fortune 500, a fir Geschäfter mat engem Publikum vun net méi wéi 500 Benotzer. All dës Zäit hunn eis Ingenieuren de Backend haaptsächlech am PHP entwéckelt. Awer virun zwee Joer huet eppes e groussen Impakt net nëmmen op d'Performance vun eise Produkter gemaach, awer och op hir Skalierbarkeet - mir hunn Golang (Go) an eisen Technologiestack agefouert.

Bal direkt hu mir entdeckt datt Go et eis erlaabt méi grouss Uwendungen mat bis zu 40x méi séier Leeschtung ze bauen. Mat et konnte mir existent Produkter ausbauen, déi a PHP geschriwwe sinn, se verbesseren andeems se d'Virdeeler vu béide Sprooche kombinéieren.

Mir wäerten Iech soen wéi eng Kombinatioun vu Go a PHP hëlleft reell Entwécklungsproblemer ze léisen a wéi et zu engem Tool fir eis ëmgewandelt gouf, dat e puer vun de Problemer eliminéiere kann PHP Stierwen Modell.

Är alldeeglech PHP Entwécklung Ëmfeld

Ier mir schwätzen iwwer wéi Dir Go benotze kënnt fir dem PHP säi stierwende Modell z'erliewen, loosst eis Äert Standard PHP Entwécklungsëmfeld kucken.

An deene meeschte Fäll leeft Dir d'Applikatioun mat enger Kombinatioun vum nginx Webserver an PHP-FPM Server. Déi éischt servéiert statesch Dateien a redirectéiert spezifesch Ufroen op PHP-FPM, an PHP-FPM selwer féiert PHP Code aus. Vläicht benotzt Dir eng manner populär Kombinatioun vun Apache a mod_php. Awer obwuel et e bëssen anescht funktionnéiert, sinn d'Prinzipien déiselwecht.

Loosst eis kucken wéi PHP-FPM Applikatiounscode ausféiert. Wann eng Ufro ukomm ass, initialiséiert PHP-FPM de Kand PHP Prozess a passéiert d'Detailer vun der Ufro als Deel vu sengem Zoustand (_GET, _POST, _SERVER, etc.).

De Staat kann net während der Ausféierung vun engem PHP Skript änneren, sou datt et nëmmen ee Wee gëtt fir en neie Set vun Inputdaten ze kréien: andeems Dir d'Prozessspeicher läscht an et nei initialiséiert.

Dësen Ausféierungsmodell huet vill Virdeeler. Dir musst Iech net vill Suergen iwwer Erënnerung Konsum, all Prozesser sinn komplett isoléiert, a wann ee vun hinnen stierft, gëtt automatesch erstallt ouni de Rescht vun de Prozesser Afloss. Awer dës Approche huet och Nodeeler déi schéngen wann Dir probéiert d'Applikatioun ze skaléieren.

Nodeeler an Ineffizienz vun engem reguläre PHP Ëmfeld

Wann Dir an der berufflecher Entwécklung am PHP engagéiert sidd, da wësst Dir wou Dir en neie Projet ufänkt - andeems Dir e Kader auswielt. Et besteet aus Bibliothéike fir Ofhängegkeetsinjektioun, ORMs, Iwwersetzungen a Templates. An natierlech kënnen all Benotzerinput bequem an een Objet gesat ginn (Symfony / HTTPFoundation oder PSR-7). Kaderen sinn cool!

Awer alles huet säi Präis. An all Enterprise-Niveau Kader, fir eng einfach Benotzer Ufro ze veraarbecht oder Zougang zu enger Datebank, Dir musst op d'mannst Dosende vu Fichieren lued, vill Klassen erstellen a verschidde Konfiguratiounen parse. Awer dat Schlëmmst ass datt Dir no all Aufgab ofgeschloss musst alles zrécksetzen an erëm ufänken: all de Code deen Dir just initiéiert huet gëtt nëtzlos, mat senger Hëllef wäert Dir net méi eng aner Ufro veraarbecht. Sot dëst zu all Programméierer deen an all aner Sprooch schreift, an Dir wäert bewilderment op sengem Gesiicht gesinn.

PHP-Ingenieuren hu jorelaang no Weeër gesicht fir dëse Problem ze léisen, mat clever fauler Luede Techniken, Mikroframeworks, optimiséierte Bibliothéiken, Cache, asw.. Mä am Endeffekt musst Dir nach ëmmer déi ganz Applikatioun zrécksetzen an ëmmer erëm ufänken. (Notiz vum Iwwersetzer: Dëse Problem gëtt deelweis geléist mat der Advent vun virlueden an PHP 7.4)

Kann PHP mat Go méi wéi eng Ufro iwwerliewen?

Et ass méiglech PHP Scripten ze schreiwen déi méi laang wéi e puer Minutten daueren (bis zu Stonnen oder Deeg): zum Beispill Cron Aufgaben, CSV Parser, Queue Buster. Si schaffen all nom selwechte Szenario: si recuperéieren eng Aufgab, maachen se aus a waarden op déi nächst. De Code wunnt an der Erënnerung, spuert wäertvoll Millisekonnen well vill zousätzlech Schrëtt erfuerderlech sinn fir de Kader an d'Applikatioun ze lueden.

Awer laanglieweg Scripten entwéckelen ass net sou einfach. All Fehler killt de Prozess komplett ëm, d'Diagnos vun Erënnerungslecks mécht Iech verréckt, an Dir kënnt net méi F5 Debugging benotzen.

D'Situatioun ass verbessert mat der Verëffentlechung vu PHP 7: en zouverléissege Müllsammler ass erschéngt, et ass méi einfach ginn fir Feeler ze handhaben, an d'Kernelverlängerunge sinn elo vu Leck geschützt. Richteg, d'Ingenieuren mussen nach ëmmer virsiichteg sinn mat Erënnerung a bewosst sinn iwwer staatlech Themen am Code (gëtt et eng Sprooch wou mir keng Suergen iwwer dës Saache musse maachen?). An awer, am PHP 7, waarden manner Iwwerraschungen op eis.

Ass et méiglech de Modell ze huelen fir mat laangliewege PHP Scripten ze schaffen, et un méi trivial Aufgaben z'adaptéieren wéi d'Veraarbechtung vun HTTP-Ufroen, an doduerch d'Noutwendegkeet eliminéiert fir alles vun Null fir all Ufro ze lueden?

Fir dëse Problem ze léisen, musse mir als éischt eng Serverapplikatioun implementéieren déi HTTP-Ufroe akzeptéiere konnt an se een nom aneren un de PHP-Aarbechter weiderginn ouni et all Kéier ëmzebréngen.

Mir woussten datt mir e Webserver a pure PHP (PHP-PM) schreiwen oder d'C Extensioun (Swoole) benotzen. An obwuel all Method seng eege Verdéngschter huet, hunn déi zwou Optiounen eis net gepasst - mir wollten eppes méi. Mir brauche méi wéi nëmmen e Webserver - mir hu gehofft eng Léisung ze kréien, déi eis vun de Problemer, déi mam "haarden Start" an PHP verbonne sinn, retten kéint, déi gläichzäiteg liicht adaptéiert an ausgebaut kënne ginn fir spezifesch Applikatiounen. Dat ass, mir brauche en Applikatiounsserver.

Kann Go mat dësem hëllefen? Mir woussten et kéint well d'Sprooch Applikatiounen an eenzel Binären kompiléiert; et ass Cross-Plattform; benotzt säin eegene, ganz elegant, parallele Veraarbechtungsmodell (Konkurrenz) a Bibliothéik fir mat HTTP ze schaffen; an endlech, Dausende vun Open-Source Bibliothéiken an integrations wäert fir eis sinn.

Schwieregkeete fir zwou Programméierungssproochen ze kombinéieren

Den éischte Schrëtt war ze bestëmmen wéi zwou oder méi Uwendungen matenee kommunizéieren.

Zum Beispill, benotzt wonnerbar Bibliothéik Den Alex Palaestras konnt Erënnerungsdeelen tëscht PHP a Go Prozesser implementéieren (ähnlech wéi mod_php an Apache). Awer dës Bibliothéik huet Features déi hir Notzung limitéieren fir eise Problem ze léisen.

Mir hunn decidéiert eng aner, méi heefeg Approche ze benotzen: Interaktioun tëscht Prozesser duerch Sockets / Pipelines ze bauen. Dës Approche huet seng Zouverlässegkeet an de leschte Joerzéngte bewisen a gouf um Betribssystemniveau gutt optimiséiert.

Fir unzefänken hu mir en einfache binäre Protokoll erstallt fir Datenaustausch tëscht Prozesser an Ëmgank mat Iwwerdroungsfehler. A senger einfachster Form ass dës Aart vu Protokoll ähnlech wéi netstring с fix Gréisst Pak Header (an eisem Fall 17 Bytes), déi Informatioun iwwer d'Zort vum Paket, seng Gréisst an eng binär Mask enthält fir d'Integritéit vun Daten ze kontrolléieren.

Op der PHP Säit hu mir benotzt pack Funktioun, an op der Go Säit - eng Bibliothéik Kodéierung / binär.

Et huet eis geschéngt datt ee Protokoll net genuch wier - also hu mir d'Fäegkeet bäigefüügt ze ruffen Gitt Servicer net / rpc direkt vu PHP. Dëst huet eis spéider vill an der Entwécklung gehollef, well mir Go-Bibliothéiken einfach an PHP-Applikatiounen integréiere konnten. D'Resultat vun dëser Aarbecht kann zum Beispill an eisem aneren Open-Source Produkt gesi ginn Goridge.

Verdeelen Aufgaben iwwer verschidde PHP Aarbechter

Nodeems mir den Interaktiounsmechanismus ëmgesat hunn, hu mir ugefaang ze denken wéi mir am effizientesten Aufgaben op PHP Prozesser transferéieren. Wann eng Aufgab ukomm ass, muss den Applikatiounsserver e gratis Aarbechter auswielen fir se ofzeschléissen. Wann en Aarbechter / Prozess mat engem Feeler ofschléisst oder "stierft", gi mir entlooss a kreéieren en neien fir en ze ersetzen. A wann den Aarbechter/Prozess erfollegräich ofgeschloss ass, gi mir et zréck an de Pool vun den Aarbechter, déi verfügbar sinn fir Aufgaben auszeféieren.

RoadRunner: PHP ass net gebaut fir ze stierwen, oder Golang fir d'Rettung

Fir e Pool vun aktiven Aarbechter ze späicheren, hu mir benotzt gebufferten Kanal, Fir onerwaart "dout" Aarbechter aus dem Pool ze läschen, hu mir e Mechanismus bäigefüügt fir Feeler an Aarbechterzoustand ze verfolgen.

Als Resultat hu mir e funktionnéierende PHP-Server kritt, deen fäeg ass all Ufroen a binärer Form ze veraarbecht.

Fir datt eis Applikatioun als Webserver funktionnéiert, hu mir en zouverléissege PHP-Standard misse wielen fir all erakommen HTTP-Ufroen ze representéieren. An eisem Fall mir just transforméieren net/http Ufro vum Go to Format PSR-7sou datt et kompatibel ass mat de meeschte PHP Kaderen déi haut verfügbar sinn.

Well PSR-7 als onverännerbar ugesi gëtt (e puer géifen technesch soen datt et net ass), mussen d'Entwéckler Uwendungen schreiwen déi d'Ufro net grondsätzlech als eng global Entitéit behandelen. Dëst passt gutt mam Konzept vu laangliewege PHP Prozesser. Eis lescht Ëmsetzung, déi nach net genannt gouf, huet esou ausgesinn:

RoadRunner: PHP ass net gebaut fir ze stierwen, oder Golang fir d'Rettung

Aféierung RoadRunner - héich-Performance PHP Applikatioun Server

Eis éischt Testaufgab war den API Backend, deen periodesch onerwaart Bursts vun Ufroen erlieft huet (vill méi dacks wéi soss). Och wann nginx an deene meeschte Fäll genuch war, hu mir regelméisseg 502 Feeler begéint, well mir de System net séier genuch ausbalancéiere konnten fir déi erwaart Erhéijung vun der Belaaschtung.

Fir dës Léisung ze ersetzen, hu mir eisen éischte PHP/Go Applikatiounsserver am fréien 2018 ofgebaut. An direkt krute mir en onheemlechen Effekt! Net nëmmen hu mir den 502-Fehler komplett entlooss, mä mir konnten och d'Zuel vun de Serveren ëm zwee-Drëttel reduzéieren, vill Suen a Kappwéi fir Ingenieuren a Produktmanager spueren.

Bis Mëtt vum Joer hu mir eis Léisung perfektionéiert, se op GitHub ënner der MIT Lizenz publizéiert an et genannt RoadRunner, doduerch seng onheemlech Geschwindegkeet an Effizienz ënnersträichen.

Wéi RoadRunner kann Ären Entwécklungsstack verbesseren

Applikatioun RoadRunner erlaabt eis Middleware net / http op der Go Säit ze benotzen fir JWT Verifizéierung ze maachen ier d'Ufro souguer PHP trefft, wéi och fir WebSockets a global Staatsaggregatioun am Prometheus ze handhaben.

Dank dem agebaute RPC kënnt Dir d'API vun all Go-Bibliothéiken fir PHP opmaachen ouni Extensiounswrapper ze schreiwen. Méi wichteg, RoadRunner ka benotzt ginn fir nei Net-HTTP Serveren z'installéieren. Beispiller enthalen lancéiere Handler an PHP AWS Lambda, Schafen zouverlässeg Schlaang Busters a souguer dobäi gRPC op eis Applikatiounen.

Mat der Hëllef vun de PHP- a Go-Communautéiten hu mir d'Stabilitéit vun der Léisung erhéicht, d'Appleistung ëm bis zu 40 Mol an e puer Tester erhéicht, verbessert Debugging-Tools, implementéiert Integratioun mam Symfony-Framework, a bäigefüügt Ënnerstëtzung fir HTTPS, HTTP/ 2, Plugins a PSR-17.

Konklusioun

E puer Leit sinn nach ëmmer an der aler Vue vu PHP gefaangen als eng lues, ëmständlech Sprooch nëmme gutt fir WordPress Plugins ze schreiwen. Dës Leit kéinte souguer soen datt PHP eng Begrenzung huet: Wann d'Applikatioun grouss genuch gëtt, musst Dir eng méi "reife" Sprooch wielen an d'Codebasis iwwerschreiwe, déi iwwer ville Joer accumuléiert ass.

Op dat alles wëll ech äntweren: Denkt nach eng Kéier. Mir gleewen datt nëmmen Dir all Restriktiounen fir PHP setzen kënnt. Dir kënnt Äert ganzt Liewen verbréngen vun enger Sprooch op déi aner ze sprangen, probéiert de perfekte Match fir Är Bedierfnesser ze fannen, oder Dir kënnt u Sproochen als Tools denken. Déi ugesi Mängel vun enger Sprooch wéi PHP kënnen tatsächlech d'Grënn fir säin Erfolleg sinn. A wann Dir et mat enger anerer Sprooch wéi Go kombinéiert, kënnt Dir vill méi mächteg Produkter kreéieren wéi wann Dir op nëmmen eng Sprooch limitéiert wier.

Nodeems mir mat enger Kombinatioun vu Go a PHP geschafft hunn, kënne mir soen datt mir se gär hunn. Mir plangen net ee fir deen aneren opzebréngen, mee kucken éischter no Weeër fir nach méi Wäert aus dësem Dual Stack ze kréien.

UPD: Mir begréissen den Ersteller vum RoadRunner a Co-Autor vum originelle Artikel - Lachesis

Source: will.com

Setzt e Commentaire