RoadRunner: PHP өлүү үчүн, же Голанг куткаруу үчүн курулган эмес

RoadRunner: PHP өлүү үчүн, же Голанг куткаруу үчүн курулган эмес

Салам, Хабр! Биз Badooдо активдүүбүз PHP аткаруу боюнча иштөө, бизде бул тилде кыйла чоң система болгондуктан жана аткаруу маселеси акчаны үнөмдөө маселеси болуп саналат. Он жылдан ашык убакыт мурун биз бул үчүн PHP-FPM түздүк, ал адегенде PHP үчүн патчтардын топтому болгон, кийинчерээк расмий дистрибуциянын бир бөлүгү болуп калды.

Акыркы жылдары РНР чоң ийгиликтерге жетишти: таштанды жыйноочу жакшырды, туруктуулуктун деңгээли жогорулады – бүгүнкү күндө PHPде демондорду жана узак мөөнөттүү скрипттерди эч кандай көйгөйсүз жаза аласыз. Бул Spiral Scout-ка андан ары барууга мүмкүндүк берди: RoadRunner, PHP-FPMден айырмаланып, сурамдардын ортосундагы эстутумду тазалабайт, бул кошумча аткаруу артыкчылыктарын берет (бирок бул ыкма иштеп чыгуу процессин татаалдантат). Учурда биз бул куралды сынап жатабыз, бирок азырынча бөлүшө турган жыйынтыктарыбыз жок. Аларды күтүүнү кызыктуураак кылуу үчүн, Биз Spiral Scoutтен RoadRunner жарыясынын котормосун жарыялап жатабыз.

Макаладагы ыкма бизге жакын: көйгөйлөрүбүздү чечүүдө биз көбүнчө PHP жана Go айкалыштарын колдонобуз, эки тилдин тең пайдасын алып, биринин пайдасына экинчисинен баш тартпайбыз.

Ээ!

Акыркы он жылдын ичинде биз тизмедеги компаниялар үчүн арыздарды түздүк Fortune 500, жана аудиториясы 500 колдонуучудан ашпаган ишканалар үчүн. Бул убакыттын ичинде биздин инженерлер негизинен PHPде бэкэндди иштеп чыгышты. Бирок эки жыл мурун бир нерсе биздин өнүмдөрдүн иштешине гана эмес, алардын масштабдуулугуна да чоң таасирин тийгизди - биз Голанг (Go) технологиялык стекибизге киргиздик.

Дээрлик дароо эле Go бизге 40 эсеге чейин ылдамыраак иштеши менен чоңураак тиркемелерди курууга мүмкүндүк бергенин таптык. Аны менен биз эки тилдин артыкчылыктарын айкалыштыруу менен аларды өркүндөтүп, PHPде жазылган өнүмдөрдү кеңейте алдык.

Биз сизге Go жана PHP айкалышы реалдуу өнүгүү көйгөйлөрүн чечүүгө кандайча жардам берерин жана ал биз үчүн кандайча айрым көйгөйлөрдү жок кыла турган куралга айланганын айтып беребиз. PHP өлүп жаткан модель.

Сиздин күнүмдүк PHP өнүктүрүү чөйрөңүз

PHPдин өлүп бара жаткан моделин жандандыруу үчүн Goну кантип колдонсоңуз болору жөнүндө сөз кылуудан мурун, келиңиз, сиздин стандарттуу PHP иштеп чыгуу чөйрөңүздү карап көрөлү.

Көпчүлүк учурларда, сиз тиркемени nginx веб серверинин жана PHP-FPM серверинин айкалышы аркылуу иштетесиз. Биринчиси статикалык файлдарды тейлейт жана конкреттүү суроо-талаптарды PHP-FPMге багыттайт, ал эми PHP-FPM өзү PHP кодун аткарат. Балким, сиз Apache жана mod_php азыраак таанымал комбинациясын колдонуп жаткандырсыз. Бирок ал бир аз башкача иштегени менен, принциптери бирдей.

Келгиле, PHP-FPM колдонмо кодун кантип аткарарын карап көрөлү. Сурам келгенде, PHP-FPM бала PHP процессин инициализациялайт жана суроо-талаптын чоо-жайын анын абалынын бир бөлүгү катары өткөрүп берет (_GET, _POST, _SERVER ж.б.).

PHP скриптинин аткарылышы учурунда абал өзгөрө албайт, ошондуктан киргизүү маалыматтарынын жаңы топтомун алуунун бир гана жолу бар: процесстин эс тутумун тазалоо жана аны кайра баштоо.

Бул аткаруу модели көптөгөн артыкчылыктарга ээ. Эстутум керектөө жөнүндө көп кабатырлануунун кереги жок, бардык процесстер толугу менен обочолонгон, эгер алардын бири өлсө, ал калган процесстерге таасир этпестен автоматтык түрдө кайра түзүлөт. Бирок бул ыкманын да тиркемени масштабдоо аракетинде пайда болгон кемчиликтери бар.

Кадимки PHP чөйрөсүнүн кемчиликтери жана натыйжасыздыктары

Эгер сиз PHPде профессионалдык өнүгүү менен алек болсоңуз, анда жаңы долбоорду кайдан баштоону билесиз - фреймворк тандоо менен. Ал көз карандылыкты киргизүү үчүн китепканалардан, ORM'лерден, котормолордон жана шаблондордон турат. Жана, албетте, колдонуучунун бардык киргизгенин бир объектке ыңгайлуу түрдө киргизүүгө болот (Symfony/HttpFoundation же PSR-7). Frameworks сонун!

Бирок ар бир нерсенин өз баасы болот. Кандай гана ишкана деңгээлиндеги алкакта, колдонуучунун жөнөкөй суроо-талабын иштеп чыгуу же маалымат базасына кирүү үчүн сиз жок дегенде ондогон файлдарды жүктөшүңүз керек, көптөгөн класстарды түзүп, бир нече конфигурацияларды талдооңуз керек. Бирок эң жаманы, ар бир тапшырманы аткаргандан кийин бардыгын баштапкы абалга келтирип, кайра башташыңыз керек болот: сиз жаңы эле баштаган коддун баары жараксыз болуп калат, анын жардамы менен сиз башка өтүнүчтү иштетпей каласыз. Муну башка тилде жазган каалаган программистке айтыңыз, ошондо анын жүзүнөн таң калганын көрөсүз.

PHP инженерлери акылдуу жалкоо жүктөө ыкмаларын, микрофремворкторду, оптималдаштырылган китепканаларды, кэштерди ж.б. колдонуп, бул көйгөйдү чечүүнүн жолдорун көп жылдар бою издеп көрүштү. (Котормочунун эскертүүсү: пайда болушу менен бул маселе жарым-жартылай чечилет алдын ала жүктөө PHP 7.4)

Go менен PHP бирден ашык сурамга туруштук бере алабы?

Бир нече мүнөттөн (саатка же күнгө чейин) созула турган PHP скрипттерин жазууга болот: мисалы, cron тапшырмалары, CSV талдоочулары, кезекти бузуучулар. Алардын баары бирдей сценарий боюнча иштешет: алар тапшырманы алып, аны аткарышат жана кийинкисин күтүшөт. Код эстутумда сакталып, баалуу миллисекунддарды үнөмдөйт, анткени алкакты жана тиркемени жүктөө үчүн көптөгөн кошумча кадамдар талап кылынат.

Бирок узак мөөнөттүү сценарийлерди иштеп чыгуу анчалык деле оңой эмес. Ар кандай ката процессти толугу менен өлтүрөт, эс тутумдун агып кетишин диагностикалоо сизди жинди кылат жана F5 мүчүлүштүктөрдү оңдоону мындан ары колдоно албайсыз.

PHP 7нин чыгышы менен абал жакшырды: ишенимдүү таштанды жыйноочу пайда болду, каталарды башкаруу оңой болуп калды жана ядронун кеңейтүүлөрү эми агып кетүүдөн корголду. Ырас, инженерлер дагы эле эс тутумга этият болуп, коддогу мамлекеттик маселелерден кабардар болушу керек (бул нерселер жөнүндө тынчсызданбай турган тил барбы?). Ошондой болсо да, PHP 7де бизди азыраак сюрприз күтүп турат.

Узак мөөнөттүү PHP скрипттери менен иштөө моделин алып, аны HTTP сурамдарын иштетүү сыяктуу майда-чүйдө иштерге ыңгайлаштыруу жана ошону менен ар бир суроо үчүн баарын нөлдөн баштап жүктөө зарылдыгын жок кылуу мүмкүнбү?

Бул көйгөйдү чечүү үчүн, биз адегенде HTTP сурамдарын кабыл ала турган сервердик тиркемени ишке киргизишибиз керек болчу жана аларды ар бир жолу өлтүрбөстөн PHP жумушчусуна бир-бирден жөнөтүшүбүз керек.

Биз таза PHP (PHP-PM) же C кеңейтүүсүн (Swoole) колдонуу менен веб-серверди жаза аларыбызды билчүбүз. Ар бир ыкманын өзүнүн артыкчылыктары бар болсо да, эки вариант тең бизге туура келген жок - биз дагы бир нерсени кааладык. Бизге жөн гана веб-сервер эмес, PHPдеги “катуу баштоо” менен байланышкан көйгөйлөрдөн куткара турган чечимди алабыз деп үмүттөндүк, аны ошол эле учурда конкреттүү тиркемелер үчүн оңой эле ыңгайлаштырууга жана кеңейтүүгө болот. Башкача айтканда, бизге колдонмо сервери керек болчу.

Go буга жардам бере алабы? Бул тил тиркемелерди бирдиктүү экилик форматтарга компиляциялагандыктан, биз муну билчүбүз; бул кросс-платформа; HTTP менен иштөө үчүн өзүнүн, абдан жарашыктуу, параллелдүү иштетүү моделин (конcurrency) жана китепкананы колдонот; жана акырында, миңдеген ачык булактуу китепканалар жана интеграциялар бизге жеткиликтүү болот.

Эки программалоо тилин айкалыштыруудагы кыйынчылыктар

Биринчи кадам эки же андан көп тиркемелер бири-бири менен кантип байланыша турганын аныктоо болгон.

Мисалы, колдонуу сонун китепкана Alex Palaestras PHP жана Go процесстеринин ортосунда эстутум бөлүшүүнү ишке ашыра алат (Apacheдеги mod_php сыяктуу). Бирок бул китепкана биздин көйгөйдү чечүү үчүн колдонууну чектеген өзгөчөлүктөргө ээ.

Биз башка, кеңири таралган ыкманы колдонууну чечтик: розеткалар/трубалар аркылуу процесстердин ортосундагы өз ара аракеттенүүнү куруу. Бул ыкма акыркы он жылдыкта өзүнүн ишенимдүүлүгүн далилдеди жана операциялык системанын деңгээлинде жакшы оптималдаштырылган.

Баштоо үчүн, процесстер арасында маалымат алмашуу жана берүү каталарын чечүү үчүн жөнөкөй экилик протоколду түздүк. Жөнөкөй түрдө, протоколдун бул түрү окшош netstring с белгиленген өлчөмдөгү пакеттин аталышы (биздин учурда 17 байт), анда пакеттин түрү, анын өлчөмү жана маалыматтардын бүтүндүгүн текшерүү үчүн бинардык маска жөнүндө маалымат камтылган.

PHP тарабында биз колдонгон пакет функциясы, жана Баруу тарабында - китепкана коддоо/экилик.

Бизге бир протокол жетишсиз болуп көрүндү - ошондуктан биз чалуу мүмкүнчүлүгүн коштук Түздөн-түз PHPден net/rpc кызматтарына өтүңүз. Бул кийинчерээк өнүгүүдө бизге көп жардам берди, анткени биз Go китепканаларын PHP тиркемелерине оңой интеграциялай алмакпыз. Бул иштин натыйжасын, мисалы, биздин башка ачык булак продуктуларынан көрүүгө болот Горидж.

Бир нече PHP кызматкерлерине тапшырмаларды бөлүштүрүү

Өз ара аракеттенүү механизмин ишке ашыргандан кийин, биз PHP процесстерине тапшырмаларды кантип эффективдүү өткөрүү жөнүндө ойлоно баштадык. Тапшырма келгенде, колдонмо сервери аны аткаруу үчүн акысыз жумушчуну тандашы керек. Эгерде жумушчу/процесс ката менен аяктаса же “өлүп калса”, биз андан кутулабыз жана анын ордуна жаңысын түзөбүз. Жана эгерде жумушчу/процесс ийгиликтүү аяктаса, биз аны тапшырмаларды аткаруу үчүн жеткиликтүү жумушчулардын пулуна кайтарып беребиз.

RoadRunner: PHP өлүү үчүн, же Голанг куткаруу үчүн курулган эмес

Биз колдонгон активдүү жумушчулардын бассейнин сактоо үчүн буфердик канал, күтүлбөгөн жерден "өлгөн" жумушчуларды бассейнден алып салуу үчүн, биз каталарды жана жумушчу мамлекеттерди көзөмөлдөө механизмин коштук.

Натыйжада, биз экилик түрдө берилген бардык суроо-талаптарды иштетүүгө жөндөмдүү иштеген PHP серверин алдык.

Биздин тиркеме веб-сервер катары иштеши үчүн, биз келген HTTP суроо-талаптарын көрсөтүү үчүн ишенимдүү PHP стандартын тандап алышыбыз керек болчу. Биздин учурда биз жөн гана өзгөртүү Форматка өтүүдөн net/http сурамы PSR-7Ошентип, ал бүгүнкү күндө бар көпчүлүк PHP алкактары менен шайкеш келет.

PSR-7 өзгөрүлгүс деп эсептелгендиктен (кээ бирөөлөр техникалык жактан андай эмес деп айтышат), иштеп чыгуучулар өтүнүчтү глобалдык объект катары карабаган тиркемелерди жазышы керек. Бул узак мөөнөттүү PHP процесстеринин концепциясына жакшы төп келет. Биздин акыркы ишке ашыруу, али атала элек, мындай көрүндү:

RoadRunner: PHP өлүү үчүн, же Голанг куткаруу үчүн курулган эмес

RoadRunner менен таанышуу - жогорку натыйжалуу PHP колдонмо сервери

Биздин биринчи сыноо тапшырмабыз мезгил-мезгили менен күтүлбөгөн суроо-талаптарды баштан кечирген API бэкэнди болгон (демейдегиден алда канча көп). Көпчүлүк учурларда nginx жетиштүү болгонуна карабастан, биз 502 катага дайыма туш болуп турчубуз, анткени жүктүн күтүлгөн өсүшү үчүн системаны тез арада тең салмактай алган жокпуз.

Бул чечимди алмаштыруу үчүн биз биринчи PHP/Go тиркеме серверибизди 2018-жылдын башында орноттук. Ошол замат биз укмуштуудай эффект алдык! Биз 502 катасынан толугу менен кутулуп гана тим болбостон, серверлердин санын үчтөн экиге кыскарта алдык, инженерлердин жана продукт менеджерлеринин көп акчасын жана баш оорусун үнөмдөй алдык.

Жылдын ортосуна чейин биз чечимибизди өркүндөтүп, аны MIT лицензиясы боюнча GitHub сайтында жарыяладык жана аны атадык. Roadrunner, ошону менен анын укмуштуудай ылдамдыгын жана натыйжалуулугун баса белгилейт.

RoadRunner сиздин өнүгүү стекиңизди кантип жакшыртат

арыз Roadrunner сурам PHPге жеткенге чейин JWT текшерүүсүн жүргүзүү үчүн, ошондой эле Prometheus'та WebSockets жана глобалдык абалды бириктирүү үчүн Go тарабында Middleware net/http колдонууга мүмкүнчүлүк берди.

Орнотулган RPCдин аркасында сиз PHP үчүн каалаган Go китепканаларынын API'син кеңейтүү пакеттерин жазбастан ача аласыз. Андан да маанилүүсү, RoadRunner жаңы HTTP эмес серверлерди жайылтуу үчүн колдонулушу мүмкүн. Мисалдар PHPде ишке киргизүү иштеткичтерин камтыйт AWS Lambda, ишенимдүү кезектеги бустерлерди түзүү жана ал тургай кошуу gRPC биздин колдонмолорго.

PHP жана Go жамааттарынын жардамы менен биз чечимдин туруктуулугун жогорулаттык, кээ бир тесттерде тиркеменин иштешин 40 эсеге чейин жогорулаттык, мүчүлүштүктөрдү оңдоо куралдарын жакшырттык, Symfony алкактары менен интеграцияны ишке ашырдык жана HTTPS, HTTP/ үчүн колдоону коштук. 2, плагиндер жана PSR-17.

жыйынтыктоо

Кээ бир адамдар дагы эле WordPress плагиндерин жазуу үчүн гана жарактуу жай, түйшүктүү тил катары PHPдин эскирген көз карашында. Бул адамдар PHPде чектөө бар деп айтышы мүмкүн: тиркеме жетиштүү чоңойгондо, сиз "жетилген" тилди тандап, көп жылдар бою топтолгон код базасын кайра жазышыңыз керек.

Мунун баарына мен жооп бергим келет: дагы бир жолу ойлон. Биз PHP үчүн кандайдыр бир чектөөлөрдү сиз гана кое аласыз деп ишенебиз. Сиз бүт өмүрүңүздү бир тилден экинчи тилге секирип, муктаждыктарыңызга эң сонун дал келген тилди табууга аракет кылып өткөрө аласыз же тилдерди курал катары ойлоп баштасаңыз болот. PHP сыяктуу тилдин кабыл алынган кемчиликтери анын ийгилигинин себептери болушу мүмкүн. Эгер сиз аны Go сыяктуу башка тил менен айкалыштырсаңыз, бир тил менен чектелгенге караганда алда канча күчтүү өнүмдөрдү түзө аласыз.

Go жана PHP айкалышы менен иштегендиктен, биз аларды жакшы көрөбүз деп айта алабыз. Биз бири-бирибизди курмандыкка чалууну пландаган жокпуз, тескерисинче, бул кош стектен дагы көбүрөөк баалуулуктарды алуу жолдорун издейбиз.

UPD: Биз RoadRunner түзүүчүсүн жана түпнуска макаланын авторлошун куттуктайбыз - Lachesis

Source: www.habr.com

Комментарий кошуу