„Uszanowanko Programowanko”: Not your grandpa's PHP

Liczba odsłon: 111

Język PHP prze­szedł da­le­ką dro­gę. Na po­cząt­ku był pros­tym ję­zy­kiem skryp­to­wym ułat­wia­ją­cym bu­do­wa­nie dyna­micz­nych stron WWW z nie­wiel­kim udzia­łem zmie­nia­ją­cej się treś­ci. Później zy­skał moż­li­wość pro­gra­mo­wa­nia obiek­to­we­go i stał się sze­ro­ko sto­so­wa­nym roz­wią­za­niem. Dzisiaj jest to peł­no­praw­ny obiek­to­wy ję­zyk pro­gra­mo­wa­nia, ukie­run­ko­wa­ny na bu­do­wa­nie skom­pli­ko­wa­nych apli­kac­ji sie­cio­wych. I choć wciąż jest pe­łen na­le­cia­łoś­ci, któ­re utrud­nia­ją je­go zro­zu­mie­nie lub komp­li­ku­ją rze­czy pros­te, jest to już zu­peł­nie in­ny ję­zyk pro­gra­mo­wa­nia, po­zwa­la­ją­cy na sto­so­wa­nie wie­lu cie­ka­wych tech­nik i roz­wią­zań. XXX spot­ka­nie zor­ga­ni­zo­wa­ne w ra­mach cyk­lu „Uszanowanko Programowanko” przez fir­mę The Software House, któ­re od­by­ło się 8 sierp­nia w gli­wic­kiej sie­dzi­bie fir­my, mia­ło na ce­lu za­pre­zen­to­wa­nie kil­ku naj­now­szych roz­wią­zań po­wo­du­ją­cych, że PHP mo­że kon­ku­ro­wać z in­ny­mi wy­so­ce funkcjo­nal­ny­mi plat­for­ma­mi two­rze­nia apli­kac­ji sie­cio­wych.

Pierwszą pre­zen­tac­ję, za­ty­tu­ło­wa­ną „Jak stwo­rzyć API szyb­ko, ale jed­no­cześ­nie po­rząd­nie”, przed­sta­wił Piotr Brzezina. Opisał on osno­wę pro­gra­mi­stycz­ną API Platform, poz­wa­la­ją­cą na zauto­ma­ty­zo­wa­nie two­rze­nia inter­fej­sów REST w ję­zy­ku PHP. Choć ję­zyk ten nie dys­po­nu­je me­cha­niz­mem ad­no­tac­ji, moż­na go za­stą­pić me­ta-in­for­mac­ja­mi umiesz­cza­ny­mi w ko­men­ta­rzach do klas i me­tod. API Platform ko­rzy­sta z ta­kie­go roz­wią­za­nia, po­zwa­la­jąc pro­gra­mi­ście abstrak­cyj­nie opi­sać do­stęp REST do obiek­to­wych zbio­rów da­nych w spo­sób po­dob­ny do sto­so­wa­ne­go w ję­zy­ku Java.

Stworze­nie ser­we­ra REST spro­wa­dza się do ozna­cze­nia klas en­cji od­po­wied­ni­mi ad­no­tac­ja­mi. Osnowa two­rzy w tym mo­men­cie auto­ma­tycz­nie kod ob­słu­gu­ją­cy właś­ci­we me­to­dy pro­to­ko­łu HTTP tak, aby po­wstał peł­no­praw­ny inter­fejs CRUD po­zwa­la­ją­cy na prze­glą­da­nie i mo­dy­fi­ko­wa­nie ko­lek­cji da­nych. Na tym nie koń­czą się jed­nak jej moż­li­woś­ci. Dodatkowymi ad­no­tac­ja­mi mo­że­my do­dać włas­ne punk­ty koń­co­we, roz­sze­rza­jąc stwo­rzo­ne API, wpro­wa­dzić ogra­ni­cze­nia do­stę­pu do za­so­bu w za­leż­noś­ci od ro­li użyt­kow­ni­ka, a tak­że udos­tęp­nić moż­li­wość wy­szu­ki­wa­nia ele­men­tów wed­ług war­toś­ci do­wol­nych pól, włą­cza­jąc w to wy­szu­ki­wa­nie peł­no­teks­to­we.

Osnowa do­sko­na­le ra­dzi so­bie z pros­ty­mi oraz za­gnież­dżo­ny­mi ko­lek­cja­mi da­nych. Po wska­za­niu za­leż­noś­ci mię­dzy obiek­ta­mi stwo­rzo­ne API po­zwa­la od­wo­ły­wać się za­rów­no do ca­ło­ści ko­lek­cji, jak i do po­szcze­gól­nych ele­men­tów skła­do­wych. Można też okre­ślać po­ziom szcze­gó­ło­wo­ści zwra­ca­nych en­cji, co po­zwa­la unik­nąć nie­pot­rzeb­ne­go po­bie­ra­nia przez apli­ka­cję kli­enc­ką szcze­gó­ło­wej za­war­toś­ci ob­szer­nych obiek­tów w przy­pad­ku, gdy po­trzeb­na jest tyl­ko li­sta naj­waż­niej­szych ich cech.

Dodatko­wą za­le­tą API Platform jest auto­ma­ty­zac­ja ge­ne­ro­wa­nia do­ku­men­ta­cji do stwo­rzo­ne­go API. Oczywiś­cie, trze­ba wpro­wa­dzić włas­ne, moż­li­wie ob­szer­ne ko­men­ta­rze Javadoc dla de­fi­nio­wa­nych mo­de­li en­cji oraz dla włas­nych punk­tów koń­co­wych REST, jed­nak dla wszyst­kich inter­fej­sów CRUD peł­na do­ku­men­tac­ja – uwzględ­nia­ją­ca rów­nież moż­li­wość wy­szu­ki­wa­nia da­nych oraz ogra­ni­cza­nia za­kre­su in­for­ma­cyj­ne­go – jest two­rzo­na auto­ma­tycz­nie.

API Platform moż­na zin­te­gro­wać z apli­kac­ja­mi pi­sa­ny­mi z wy­ko­rzys­ta­niem osno­wy Symfony. Możliwe jest też po­łą­cze­nie do­stę­pu CRUD z częś­cią rea­li­zo­wa­ną zgod­nie z mo­de­lem CQRS. Jedną z nie­licz­nych wad osno­wy jest brak ob­słu­gi en­cji nie­mu­to­wal­nych, jed­nak trwa­ją pra­cę nad usu­nię­ciem tej nie­do­god­noś­ci.

Zaintereso­wa­ni mo­gą po­brać tekst źród­ło­wy przy­kła­do­wej apli­kac­ji two­rzo­nej w cza­sie pre­zen­tac­ji spod adre­su https://gitlab.com/flashcards uszanowanko/api.


W dru­giej pre­zen­tac­ji, za­ty­tu­ło­wa­nej „Swoole w PHP – czy to ma sens?” i przed­sta­wio­nej przez Adriana Chlubka, po­ka­za­na zo­sta­ła moż­li­wość two­rze­nia wy­so­ko­wy­daj­nych, asyn­chro­nicz­nych mo­du­łów back-end na­pi­sa­nych w ję­zy­ku PHP. Umożliwia to bi­blio­te­ka Swoole, na­pi­sa­na w ję­zy­ku C i współ­pra­cu­ją­ca z ser­we­rem apli­kac­ji NGINX.

Za po­mo­cą Swoole moż­na pi­sać mi­kro-usłu­gi ko­mu­ni­ku­ją­ce się za po­mo­cą pro­to­ko­łu HTTP, Web­Socket lub zwyk­łych ka­na­łów TCPUDP. Zamiast zwyk­łych stron WWW, w Swoole two­rzy się asyn­chro­nicz­ne funk­cje ob­słu­gi re­a­gu­ją­ce na zda­rze­nia ta­kie jak żą­da­nie HTTP czy po­ja­wie­nie się pa­kie­tu da­nych. Ponie­waż każ­de ko­lej­ne dzia­ła­nie mo­że być uza­leż­nio­ne od zmia­ny sta­nu po­przed­nie­go, nie ma po­trze­by two­rze­nia pęt­li ocze­ki­wa­nia.

Jedną z za­let ta­kiej archi­tek­tu­ry jest moż­li­wość osiąg­nię­cia du­żej wy­daj­noś­ci. W pros­tym przy­kła­dzie ser­wu­ją­cym sta­tycz­nie za­war­tość pli­ku Swoole po­zwo­li­ło ob­słu­żyć prze­szło dwu­krot­nie wię­cej żą­dań na se­kun­dę niż zwyk­ły NGINX. Wysokie osią­gi ma­ją nie­ste­ty swo­ją ce­nę. Obsługi­wa­ny jest pro­to­kół HTTP wy­łącz­nie w wer­sji 1.0, nie ma też moż­li­woś­ci szy­fro­wa­nia ko­mu­ni­kac­ji. Obydwie kwe­stie roz­wią­zu­ją jed­nak za­zwy­czaj ser­we­ry po­śred­ni­czą­ce, i tak sto­so­wa­ne w skom­pli­ko­wa­nych in­fra­struk­tu­rach ser­we­rów apli­kac­ji sie­cio­wych.

Oprócz wspom­nia­ne­go pros­te­go przy­kła­du, pre­le­gent przed­sta­wił też dwa in­ne. Pierwszy de­mons­tro­wał moż­li­wość ob­słu­gi po­łą­czeń Web­Socket za po­mo­cą mi­ni­mal­nej iloś­ci ko­du po stro­nie ser­we­ra. Drugi po­ka­zy­wał jak po­łą­czyć ka­na­ły ko­mu­ni­kac­ji HTTPWeb­Socket w ce­lu stwo­rze­nia pros­te­go ko­mu­ni­ka­to­ra inter­ne­to­we­go. Zaintereso­wa­ni mo­gą po­brać tek­sty źród­ło­we tych apli­kac­ji spod adre­su https://github.com/achlubek/swoole experiments.


Ostatnia pre­zen­tac­ja, przed­sta­wio­na przez Franciszka Krasowskiego i za­ty­tu­ło­wa­na „PHP-PM: hit czy kit?”, po­świę­co­na zo­sta­ła akce­le­ra­to­ro­wi apli­kac­ji PHP naz­wa­ne­mu PHP Process Manager. Autorzy roz­wią­za­nia chwa­lą się na­wet pięt­nas­to­krot­nym przys­pie­sze­niem dzia­ła­nia apli­kac­ji, osiąg­nię­tym dzię­ki bez­po­śred­niej ko­mu­ni­kac­ji ser­we­ra apli­kac­ji Apache lub NGINX z pu­lą ma­szyn wir­tu­al­nych PHP. Dzięki zlik­wi­do­wa­niu po­trze­by ciąg­łe­go uru­cha­mia­nia i za­trzy­my­wa­nia nie­za­leż­nych in­stan­cji PHP oraz ścis­łej in­te­grac­ji z mo­de­lem „żą­da­nie/od­po­wiedź” uda­ło się wy­eli­mi­no­wać więk­szość na­rzu­tów cza­so­wych i znacz­nie skró­cić za­rów­no czas reali­zac­ji każ­de­go żą­da­nia, jak i opóź­nie­nie roz­po­czę­cia reali­zac­ji.

Ponie­waż inter­pre­ter PHP nie jest przy­sto­so­wa­ny do ciąg­łej pra­cy, nie­unik­nio­na jest utra­ta częś­ci za­so­bów spo­wo­do­wa­na przez wy­cie­ki pa­mię­ci. PHP-PM ni­we­lu­je ich wpływ przez re­gu­lar­ne za­trzy­my­wa­nie in­stan­cji ma­szy­ny wir­tu­al­nej PHP i ich po­now­ne uru­cha­mia­nie. Proces ten na­le­ży jed­nak sa­mo­dziel­nie do­sto­so­wać do po­trzeb uru­cha­mia­nych apli­kac­ji. Mimo to, na roz­wią­za­nie wy­ko­rzy­stu­ją­ce PHP-PM na­le­ży prze­wi­dzieć na­praw­dę po­kaź­ne za­so­by sprzę­to­we. Serwer te­sto­wy, któ­ry słu­żył do de­mons­tro­wa­nia roz­wią­za­nia oraz po­mia­rów wy­daj­noś­ci, wy­ko­rzys­ty­wał 24 GiB pa­mię­ci opera­cyj­nej na po­trze­by ser­we­ra apli­kac­ji oraz wszyst­kich ma­szyn wir­tu­al­nych.

Prelegent w ra­mach przy­go­to­wań do pre­zen­tac­ji wy­ko­nał te­sty wy­daj­noś­cio­we PHP-PM by zwe­ry­fi­ko­wać twier­dze­nia auto­rów co do wy­daj­noś­ci. Najwięk­sze przy­spie­sze­nie uda­ło się uzys­kać w przy­pad­ku pros­tej apli­kac­ji ko­rzy­sta­ją­cej z osno­wy Symfony. PHP-PM re­ali­zo­wał pięć ra­zy wię­cej ope­rac­ji na se­kun­dę niż ApacheNGINX w przy­pad­ku jed­ne­go klienta oraz dwa ra­zy wię­cej przy rów­no­leg­łym do­stę­pie wie­lu klien­tów. To dość kon­kret­ne przy­spie­sze­nie zo­sta­ło oku­pio­ne bar­dzo du­żym ob­cią­że­niem pa­mię­ci opera­cyj­nej.

Niestety, im bar­dziej skom­pli­ko­wa­ny kod stro­ny, tym mniej­sza jest prze­wa­ga PHP-PM nad stan­dar­do­wy­mi roz­wią­za­nia­mi. Rozbudo­wa­ny przy­kład ko­rzy­sta­ją­cy ze wspom­nia­ne­go wcześ­niej API Platform pra­co­wał w śro­do­wis­ku PHP-PM tyl­ko trzy­krot­nie szyb­ciej, niż w zwyk­łych ser­we­rach apli­kac­ji, utrzy­mał jed­nak ta­ką sa­mą prze­wa­gę rów­nież przy rów­no­leg­łej reali­zac­ji za­py­tań wie­lu klien­tów. Jeszcze go­rzej no­we roz­wią­za­nie po­ra­dzi­ło so­bie w przy­pad­ku apli­kac­ji ko­rzy­sta­ją­cej z osno­wy Laravel, któ­ra dzia­ła­ła tak sa­mo po­wo­li we wszyst­kich trzech tes­to­wa­nych śro­do­wis­kach.

Największą wa­dą PHP-PM jest brak ob­słu­gi „czys­te­go” ko­du PHP. Ze wzglę­du na cha­rak­ter ak­ce­le­rac­ji, apli­kac­je mu­szą ko­rzy­stać z jed­nej z ob­słu­gi­wa­nych osnów pro­gra­mis­tycz­nych, ta­kich jak Symfony czy Laravel. Do naj­po­pu­lar­niej­szych apli­kac­ji, któ­rych nie moż­na przy­spie­szyć za po­mo­cą PHP-PM na­le­ży Word­Press. Do drob­niej­szych wad na­le­ży za­li­czyć ko­niecz­ność prze­zna­cze­nia na kon­te­ner apli­kac­ji ser­we­ra o bar­dzo du­żej po­jem­noś­ci pa­mię­ci fi­zycz­nej. Nawet przy ol­brzy­mich do­stęp­nych za­so­bach, ad­mi­nis­tra­tor mu­si pra­co­wi­cie skon­fi­gu­ro­wać licz­bę in­stan­cji ma­szy­ny wir­tu­al­nej, częs­to­tli­wość po­now­ne­go uru­cha­mia­nia ma­szyn oraz ilość pa­mię­ci przy­dzie­lo­nej kon­kret­nym in­stan­cjom. Mimo speł­nie­nia wszyst­kich tych wy­mo­gów, PHP-PM mo­że nie speł­nić ocze­ki­wań lub w naj­mniej ocze­ki­wa­nych mo­men­tach zwal­niać.

PHP-PM jest bar­dzo obie­cu­ją­cym roz­wią­za­niem mo­gą­cym zna­czą­co pod­nieść wy­daj­ność apli­kac­ji o nis­kim i śred­nim po­zio­mie skom­pli­ko­wa­nia. Ze wzglę­du na wy­ma­ga­nia sprzę­to­we i ad­mi­ni­stra­cyj­ne oraz uzys­ki­wa­ny po­ziom przy­spie­sze­nia mo­że zna­leźć za­sto­so­wa­nie w cen­trach hos­tingu usług chmu­ro­wych. Wydaje się jed­nak, że przed pro­duk­tem jest jesz­cze dłu­ga dro­ga, a przy opra­co­wy­wa­niu ko­lej­nych wer­sji auto­rzy po­win­ni sku­pić się na zwięk­sze­niu wy­daj­noś­ci, pod­nie­sie­niu po­zio­mu sta­bil­noś­ci i zmniej­sze­niu po­zio­mu wy­ma­ga­nych za­so­bów sys­te­mo­wych.


Jak zwyk­le, spot­ka­nie by­ło bar­dzo do­brze zor­ga­ni­zo­wa­ne. Sesje roz­dzie­la­ły przer­wy po­zwa­la­ją­ce roz­pro­sto­wać no­gi, na uczest­ni­ków cze­ka­ły zim­ne na­po­je, a na ko­niec spot­ka­nia za­mó­wio­na zo­sta­ła piz­za. Była też moż­li­wość do in­te­gro­wa­nia się z in­ny­mi uczest­ni­ka­mi oraz za­da­wa­nia py­tań pre­le­gen­tom.