RoadRunner: PHP haijaundwa kufa, au Golang kuokoa

RoadRunner: PHP haijaundwa kufa, au Golang kuokoa

Habari, Habr! Tunafanya kazi katika Badoo kufanya kazi kwenye utendaji wa PHP, kwa kuwa tuna mfumo mkubwa kiasi katika lugha hii na suala la ufaulu ni suala la kuokoa pesa. Zaidi ya miaka kumi iliyopita, tuliunda PHP-FPM kwa hili, ambayo mara ya kwanza ilikuwa seti ya patches kwa PHP, na baadaye ikawa sehemu ya usambazaji rasmi.

Katika miaka ya hivi karibuni, PHP imefanya maendeleo makubwa: mtozaji wa takataka umeboresha, kiwango cha utulivu kimeongezeka - leo unaweza kuandika daemons na maandiko ya muda mrefu katika PHP bila matatizo yoyote. Hii iliruhusu Spiral Scout kwenda mbali zaidi: RoadRunner, tofauti na PHP-FPM, haisafishi kumbukumbu kati ya maombi, ambayo hutoa manufaa ya ziada ya utendaji (ingawa mbinu hii inatatiza mchakato wa maendeleo). Kwa sasa tunajaribu zana hii, lakini bado hatuna matokeo yoyote ya kushiriki. Ili kuifanya iwe ya kufurahisha zaidi kuwangojea, Tunachapisha tafsiri ya tangazo la RoadRunner kutoka Spiral Scout.

Njia kutoka kwa kifungu iko karibu nasi: wakati wa kutatua shida zetu, sisi pia mara nyingi hutumia mchanganyiko wa PHP na Go, kupata faida za lugha zote mbili na sio kuacha moja kwa niaba ya nyingine.

Kufurahia!

Katika kipindi cha miaka kumi iliyopita, tumeunda maombi kwa makampuni kutoka kwenye orodha Mpiga 500, na kwa biashara zilizo na hadhira ya watumiaji wasiozidi 500. Wakati huu wote, wahandisi wetu walitengeneza hali ya nyuma haswa katika PHP. Lakini miaka miwili iliyopita, kuna kitu kilifanya athari kubwa si tu kwenye utendaji wa bidhaa zetu, bali pia katika uimara wao - tulianzisha Golang (Nenda) kwenye mkusanyiko wetu wa teknolojia.

Takriban mara moja, tuligundua kuwa Go ilituruhusu kuunda programu kubwa zenye utendakazi wa hadi 40x haraka zaidi. Kwa hiyo, tuliweza kupanua bidhaa zilizopo zilizoandikwa katika PHP, kuziboresha kwa kuchanganya faida za lugha zote mbili.

Tutakuambia jinsi mchanganyiko wa Go na PHP unavyosaidia kutatua matatizo halisi ya maendeleo na jinsi umegeuka kuwa chombo kwetu ambacho kinaweza kuondoa baadhi ya matatizo yanayohusiana na PHP kufa mfano.

Mazingira yako ya Kila Siku ya Maendeleo ya PHP

Kabla hatujazungumza kuhusu jinsi unavyoweza kutumia Go ili kufufua muundo wa kufa wa PHP, hebu tuangalie mazingira yako ya kawaida ya ukuzaji wa PHP.

Mara nyingi, unaendesha programu kwa kutumia mchanganyiko wa seva ya nginx ya wavuti na seva ya PHP-FPM. Ya kwanza hutumikia faili tuli na kuelekeza maombi maalum kwa PHP-FPM, na PHP-FPM yenyewe hutekeleza msimbo wa PHP. Labda unatumia mchanganyiko maarufu sana kutoka Apache na mod_php. Lakini ingawa inafanya kazi tofauti kidogo, kanuni ni sawa.

Wacha tuangalie jinsi PHP-FPM inavyotumia nambari ya programu. Ombi linapofika, PHP-FPM huanzisha mchakato wa PHP ya mtoto na kupitisha maelezo ya ombi kama sehemu ya hali yake (_GET, _POST, _SERVER, nk.).

Hali haiwezi kubadilika wakati wa utekelezaji wa hati ya PHP, kwa hivyo kuna njia moja tu ya kupata seti mpya ya data ya pembejeo: kwa kufuta kumbukumbu ya mchakato na kuianzisha tena.

Mfano huu wa utekelezaji una faida nyingi. Sio lazima kuwa na wasiwasi sana juu ya utumiaji wa kumbukumbu, michakato yote imetengwa kabisa, na ikiwa mmoja wao atakufa, itaundwa upya kiatomati bila kuathiri michakato mingine yote. Lakini mbinu hii pia ina hasara zinazoonekana wakati wa kujaribu kuongeza programu.

Hasara na kutofaulu kwa mazingira ya kawaida ya PHP

Ikiwa unajishughulisha na maendeleo ya kitaaluma katika PHP, basi unajua wapi kuanza mradi mpya - kwa kuchagua mfumo. Inajumuisha maktaba za kudunga utegemezi, ORM, tafsiri na violezo. Na bila shaka, pembejeo zote za mtumiaji zinaweza kuwekwa kwa urahisi kwenye kitu kimoja (Symfony/HttpFoundation au PSR-7). Mifumo ni nzuri!

Lakini kila kitu kina bei yake. Katika mfumo wowote wa kiwango cha biashara, ili kuchakata ombi rahisi la mtumiaji au kufikia hifadhidata, itabidi upakie angalau faili kadhaa, kuunda madarasa mengi na kuchanganua usanidi kadhaa. Lakini jambo baya zaidi ni kwamba baada ya kukamilisha kila kazi utahitaji kuweka upya kila kitu na kuanza tena: kanuni zote ulizozianzisha hazifai, kwa msaada wake hutashughulikia tena ombi lingine. Mwambie programu yoyote ambaye anaandika kwa lugha nyingine yoyote, na utaona mshangao usoni mwake.

Wahandisi wa PHP wametumia miaka kutafuta njia za kutatua tatizo hili, kwa kutumia mbinu za upakiaji za uvivu, mifumo midogo, maktaba zilizoboreshwa, akiba, n.k. Lakini mwishowe, bado unapaswa kuweka upya programu nzima na kuanza tena, tena na tena. (Maelezo ya mtafsiri: tatizo hili litatatuliwa kwa kiasi ujio wa pakia mapema katika PHP 7.4)

PHP iliyo na Go inaweza kuishi zaidi ya ombi moja?

Inawezekana kuandika maandishi ya PHP ambayo yatadumu zaidi ya dakika chache (hadi saa au siku): kwa mfano, kazi za cron, vichanganuzi vya CSV, viboreshaji vya foleni. Wote hufanya kazi kulingana na hali sawa: wanarudisha kazi, kuitekeleza, na kungojea inayofuata. Nambari hukaa kwenye kumbukumbu, ikihifadhi milisekunde ya thamani kwani hatua nyingi za ziada zinahitajika ili kupakia mfumo na matumizi.

Lakini kutengeneza maandishi ya muda mrefu sio rahisi sana. Hitilafu yoyote inaua mchakato kabisa, kugundua uvujaji wa kumbukumbu kunakufanya uwe wazimu, na huwezi tena kutumia utatuzi wa F5.

Hali imeboreshwa na kutolewa kwa PHP 7: mtozaji wa takataka wa kuaminika ameonekana, imekuwa rahisi kushughulikia makosa, na upanuzi wa kernel sasa unalindwa kutokana na uvujaji. Kweli, wahandisi bado wanahitaji kuwa makini na kumbukumbu na kuwa na ufahamu wa masuala ya serikali katika kanuni (kuna lugha ambayo hatupaswi kuwa na wasiwasi kuhusu mambo haya?). Na bado, katika PHP 7, mshangao machache unangojea.

Je, inawezekana kuchukua kielelezo cha kufanya kazi na hati za muda mrefu za PHP, kuibadilisha kwa kazi zisizo na maana zaidi kama kusindika maombi ya HTTP, na kwa hivyo kuondoa hitaji la kupakia kila kitu kutoka mwanzo kwa kila ombi?

Ili kutatua tatizo hili, tulihitaji kwanza kutekeleza programu ya seva ambayo inaweza kukubali maombi ya HTTP na kuyatuma moja baada ya nyingine kwa mfanyakazi wa PHP bila kuiua kila wakati.

Tulijua kuwa tunaweza kuandika seva ya wavuti katika PHP safi (PHP-PM) au kutumia kiendelezi cha C (Swoole). Na ingawa kila njia ina sifa zake, chaguzi zote mbili hazikufaa - tulitaka kitu zaidi. Tulihitaji zaidi ya seva ya wavuti - tulitarajia kupata suluhisho ambalo lingeweza kutuokoa kutokana na matatizo yanayohusiana na "kuanza kwa bidii" katika PHP, ambayo wakati huo huo inaweza kubadilishwa kwa urahisi na kupanuliwa kwa programu maalum. Hiyo ni, tulihitaji seva ya programu.

Je, unaweza kwenda kusaidia na hili? Tulijua inaweza kwa sababu lugha inakusanya programu katika jozi moja; ni jukwaa la msalaba; hutumia mfano wake mwenyewe, wa kifahari sana, sambamba wa usindikaji (concurrency) na maktaba ya kufanya kazi na HTTP; na hatimaye, maelfu ya maktaba huria na miunganisho itapatikana kwetu.

Ugumu wa kuchanganya lugha mbili za programu

Hatua ya kwanza ilikuwa kuamua jinsi maombi mawili au zaidi yangewasiliana.

Kwa mfano, kutumia maktaba ya ajabu Alex Palaestras inaweza kutekeleza kushiriki kumbukumbu kati ya michakato ya PHP na Go (sawa na mod_php katika Apache). Lakini maktaba hii ina vipengele vinavyopunguza matumizi yake kwa kutatua tatizo letu.

Tuliamua kutumia mbinu nyingine, ya kawaida zaidi: kujenga mwingiliano kati ya michakato kupitia soketi/mabomba. Mbinu hii imethibitisha kuegemea kwake katika miongo kadhaa iliyopita na imeboreshwa vyema katika kiwango cha mfumo wa uendeshaji.

Kuanza, tuliunda itifaki rahisi ya binary kwa kubadilishana data kati ya michakato na kushughulikia hitilafu za uwasilishaji. Kwa fomu yake rahisi, aina hii ya itifaki ni sawa na wavu с Kichwa cha pakiti cha saizi isiyobadilika (kwa upande wetu 17 byte), ambayo ina taarifa kuhusu aina ya pakiti, ukubwa wake na mask ya binary ili kuangalia uaminifu wa data.

Kwa upande wa PHP tulitumia pakiti kazi, na kwa upande wa Go - maktaba encoding/binary.

Ilionekana kwetu kuwa itifaki moja haitoshi - kwa hivyo tuliongeza uwezo wa kupiga simu Nenda huduma net/rpc moja kwa moja kutoka PHP. Hii baadaye ilitusaidia sana katika ukuzaji, kwani tunaweza kuunganisha kwa urahisi maktaba za Go kwenye programu za PHP. Matokeo ya kazi hii yanaweza kuonekana, kwa mfano, katika bidhaa yetu nyingine ya chanzo-wazi Goriji.

Kusambaza kazi kwa wafanyikazi wengi wa PHP

Baada ya kutekeleza utaratibu wa mwingiliano, tulianza kufikiria jinsi ya kuhamisha kazi kwa ufanisi zaidi kwa michakato ya PHP. Kazi inapofika, seva ya programu lazima ichague mfanyakazi huru ili kuikamilisha. Mfanyikazi/mchakato ukikamilika kwa kosa au "kufa," tunaiondoa na kuunda mpya ili kuibadilisha. Na ikiwa mfanyakazi/mchakato umekamilika kwa mafanikio, tunairudisha kwenye kundi la wafanyikazi wanaopatikana kufanya kazi.

RoadRunner: PHP haijaundwa kufa, au Golang kuokoa

Ili kuhifadhi kundi la wafanyikazi wanaofanya kazi tulitumia kituo kilichoakibishwa, ili kuondoa wafanyakazi "waliokufa" bila kutarajia kutoka kwenye bwawa, tuliongeza utaratibu wa kufuatilia makosa na mataifa ya wafanyakazi.

Kwa hivyo, tulipokea seva ya PHP inayofanya kazi inayoweza kushughulikia maombi yoyote yaliyowasilishwa kwa njia ya binary.

Ili programu yetu ifanye kazi kama seva ya wavuti, ilitubidi kuchagua kiwango cha kuaminika cha PHP ili kuwakilisha maombi yoyote yanayoingia ya HTTP. Kwa upande wetu sisi tu kubadilisha net/http ombi kutoka kwa Go hadi umbizo PSR-7ili iendane na mifumo mingi ya PHP inayopatikana leo.

Kwa sababu PSR-7 inachukuliwa kuwa haiwezi kubadilika (wengine wanaweza kusema kiufundi sivyo), wasanidi programu wanapaswa kuandika programu ambazo kimsingi hazichukulii ombi kama huluki ya kimataifa. Hii inalingana vyema na dhana ya michakato ya muda mrefu ya PHP. Utekelezaji wetu wa mwisho, ambao ulikuwa bado haujatajwa, ulionekana kama hii:

RoadRunner: PHP haijaundwa kufa, au Golang kuokoa

Tunakuletea RoadRunner - seva ya maombi ya PHP ya utendaji wa juu

Jukumu letu la kwanza la jaribio lilikuwa urejeshaji wa nyuma wa API, ambao mara kwa mara ulikumbana na milipuko isiyotarajiwa ya maombi (mara nyingi zaidi kuliko kawaida). Ingawa nginx ilitosha katika hali nyingi, tulikumbana na hitilafu 502 mara kwa mara kwa sababu hatukuweza kusawazisha mfumo haraka vya kutosha kwa ongezeko lililotarajiwa la mzigo.

Ili kuchukua nafasi ya suluhisho hili, tulituma seva yetu ya kwanza ya PHP/Go mapema 2018. Na mara moja tulipata athari ya ajabu! Sio tu kwamba tuliondoa kabisa hitilafu ya 502, lakini pia tuliweza kupunguza idadi ya seva kwa theluthi mbili, kuokoa pesa nyingi na maumivu ya kichwa kwa wahandisi na wasimamizi wa bidhaa.

Kufikia katikati ya mwaka, tulikuwa tumekamilisha suluhisho letu, tukaichapisha kwenye GitHub chini ya leseni ya MIT, na kuiita. Roadrunner, na hivyo kusisitiza kasi na ufanisi wake wa ajabu.

Jinsi RoadRunner Inaweza Kuboresha Stack yako ya Maendeleo

Maombi Roadrunner ilituruhusu kutumia Middleware net/http kwenye upande wa Go kutekeleza uthibitishaji wa JWT kabla ya ombi hata kufikia PHP, na pia kushughulikia WebSockets na mkusanyiko wa hali ya kimataifa huko Prometheus.

Shukrani kwa RPC iliyojengewa ndani, unaweza kufungua API ya maktaba zozote za Go kwa PHP bila kuandika vifungashio vya kiendelezi. Muhimu zaidi, RoadRunner inaweza kutumika kupeleka seva mpya zisizo za HTTP. Mifano ni pamoja na kuzindua vidhibiti katika PHP AWS Lambda, kuunda viboreshaji vya foleni vya kuaminika na hata kuongeza gRPC kwa maombi yetu.

Kwa usaidizi wa jumuiya za PHP na Go, tumeongeza uthabiti wa suluhisho, tumeongeza utendakazi wa programu kwa hadi mara 40 katika baadhi ya majaribio, zana za utatuzi zilizoboreshwa, utekelezaji wa ushirikiano na mfumo wa Symfony, na kuongeza usaidizi kwa HTTPS, HTTP/ 2, programu-jalizi, na PSR-17.

Hitimisho

Baadhi ya watu bado wamenaswa katika mwonekano wa kizamani wa PHP kama lugha ya polepole na ngumu ambayo ni nzuri tu kwa kuandika programu-jalizi za WordPress. Watu hawa wanaweza hata kusema kwamba PHP ina kizuizi: wakati programu inakua ya kutosha, unapaswa kuchagua lugha "iliyokomaa" zaidi na kuandika upya msingi wa msimbo ambao umekusanya kwa miaka mingi.

Kwa haya yote nataka kujibu: fikiria tena. Tunaamini kuwa ni wewe tu unaweza kuweka vikwazo vyovyote vya PHP. Unaweza kutumia maisha yako yote kuruka kutoka lugha moja hadi nyingine, kujaribu kupata mechi inayofaa kwa mahitaji yako, au unaweza kuanza kufikiria lugha kama zana. Mapungufu yanayotambulika ya lugha kama PHP yanaweza kuwa sababu za kufaulu kwake. Na ukiichanganya na lugha nyingine kama Go, unaweza kuunda bidhaa zenye nguvu zaidi kuliko ikiwa ungetumia lugha moja pekee.

Baada ya kufanya kazi na mchanganyiko wa Go na PHP, tunaweza kusema kwamba tunawapenda. Hatuna mpango wa kutoa moja kwa ajili ya nyingine, lakini badala yake kutafuta njia za kupata thamani zaidi kutoka kwa mrundikano huu wa aina mbili.

UPD: Tunamkaribisha mtayarishaji wa RoadRunner na mwandishi mwenza wa makala asili - Lachesis

Chanzo: mapenzi.com

Kuongeza maoni