RoadRunner: PHP нь үхэхийн тулд бүтээгдээгүй, эсвэл Голанг нь аврахын тулд бүтээгдээгүй

RoadRunner: PHP нь үхэхийн тулд бүтээгдээгүй, эсвэл Голанг нь аврахын тулд бүтээгдээгүй

Сайн уу, Хабр! Бид Badoo-д идэвхтэй ажиллаж байна PHP гүйцэтгэл дээр ажиллаж байна, учир нь бид энэ хэлээр нэлээд том системтэй бөгөөд гүйцэтгэлийн асуудал нь мөнгө хэмнэх асуудал юм. Арав гаруй жилийн өмнө бид үүнд зориулж PHP-FPM-ийг бүтээсэн бөгөөд энэ нь эхэндээ PHP-д зориулсан засварууд байсан бөгөөд дараа нь албан ёсны түгээлтийн нэг хэсэг болсон.

Сүүлийн жилүүдэд PHP маш их ахиц дэвшил гаргасан: хог цуглуулагч сайжирч, тогтвортой байдлын түвшин нэмэгдсэн - өнөөдөр та PHP дээр демонууд болон урт хугацааны скриптүүдийг ямар ч асуудалгүйгээр бичиж болно. Энэ нь Spiral Scout-д цааш явах боломжийг олгосон: RoadRunner нь PHP-FPM-ээс ялгаатай нь хүсэлтүүдийн хооронд санах ойг цэвэрлэдэггүй бөгөөд энэ нь гүйцэтгэлийн нэмэлт үр өгөөжийг өгдөг (хэдийгээр энэ арга нь хөгжүүлэлтийн процессыг хүндрүүлдэг). Бид одоогоор энэ хэрэгслийг туршиж байгаа боловч бидэнд хуваалцах үр дүн алга. Тэднийг хүлээхийг илүү хөгжилтэй болгохын тулд Бид Spiral Scout-аас гаргасан RoadRunner-ийн мэдэгдлийн орчуулгыг нийтэлж байна.

Өгүүллийн арга барил нь бидэнд ойрхон байна: асуудлыг шийдэхдээ бид ихэвчлэн PHP болон Go-г хослуулан ашигладаг бөгөөд хоёр хэлний давуу талыг олж авдаг бөгөөд нэгийг нь нөгөөгийнхөө төлөө орхихгүй.

Сайхан өнгөрүүлээрэй!

Өнгөрсөн арван жилийн хугацаанд бид жагсаалтаас компаниудад зориулсан программуудыг бий болгосон Fortune 500, мөн 500-аас илүүгүй хэрэглэгчтэй бизнес эрхлэгчдэд зориулсан. Энэ бүх хугацаанд манай инженерүүд backend-ийг голчлон PHP дээр боловсруулсан. Гэхдээ хоёр жилийн өмнө ямар нэг зүйл манай бүтээгдэхүүний гүйцэтгэлд төдийгүй тэдгээрийн өргөтгөх чадварт ихээхэн нөлөөлсөн - бид Golang (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) хялбархан оруулах боломжтой. Хүрээнүүд сайхан байна!

Гэхдээ бүх зүйл өөрийн гэсэн үнэтэй байдаг. Энгийн хэрэглэгчийн хүсэлтийг боловсруулах эсвэл мэдээллийн санд хандахын тулд та хамгийн багадаа хэдэн арван файл ачаалах, олон анги үүсгэх, хэд хэдэн тохиргоог задлан шинжлэх шаардлагатай болно. Гэхдээ хамгийн муу зүйл бол ажил бүрийг дуусгасны дараа бүх зүйлийг дахин тохируулж, дахин эхлүүлэх шаардлагатай болно: таны эхлүүлсэн бүх код ашиггүй болж, түүний тусламжтайгаар та өөр хүсэлтийг боловсруулахаа болино. Үүнийг өөр хэлээр бичдэг ямар ч програмистад хэлээрэй, тэгвэл та түүний нүүрэнд эргэлзсэн байдлыг харах болно.

PHP-ийн инженерүүд ухаалаг залхуу ачаалах техник, микрофрэймворк, оновчтой номын сан, кэш зэргийг ашиглан энэ асуудлыг шийдэх арга замыг хайж олон жил зарцуулсан. Гэвч эцэст нь та програмыг бүхэлд нь дахин тохируулж, дахин дахин эхлүүлэх хэрэгтэй. (Орчуулагчийн тайлбар: энэ асуудал гарч ирснээр хэсэгчлэн шийдэгдэх болно preload 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-тэй ажиллахад өөрийн, маш гоёмсог, зэрэгцээ боловсруулалтын загвар (дагалдах) болон номын санг ашигладаг; эцэст нь олон мянган нээлттэй эхийн номын сан, интеграци бидэнд бэлэн болно.

Програмчлалын хоёр хэлийг хослуулахад тулгардаг бэрхшээлүүд

Эхний алхам нь хоёр ба түүнээс дээш програмууд хоорондоо хэрхэн харилцахыг тодорхойлох явдал байв.

Жишээлбэл, ашиглах гайхалтай номын сан Алекс Палестрас нь PHP болон Go процессуудын хооронд санах ойг хуваалцах боломжтой (Apache дахь mod_php-тэй төстэй). Гэхдээ энэ номын сан нь бидний асуудлыг шийдвэрлэхэд ашиглах боломжийг хязгаарладаг онцлогтой.

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

Эхлэхийн тулд бид процессуудын хооронд өгөгдөл солилцох, дамжуулах алдаатай ажиллах энгийн хоёртын протоколыг бүтээсэн. Энгийн хэлбэрээр энэ төрлийн протокол нь төстэй юм сүлжээ с тогтмол хэмжээтэй пакет толгой (бидний тохиолдолд 17 байт), багцын төрөл, хэмжээ, өгөгдлийн бүрэн бүтэн байдлыг шалгах хоёртын маск зэрэг мэдээллийг агуулсан.

PHP тал дээр бид ашигласан багц функц, мөн явах талд - номын сан кодчилол/хоёртын.

Нэг протокол хангалтгүй юм шиг санагдаж байсан тул бид залгах чадварыг нэмсэн PHP-ээс шууд net/rpc үйлчилгээний Go үйлчилгээ. Энэ нь хожим нь Go номын сангуудыг PHP программуудад хялбархан нэгтгэж чадсан тул хөгжүүлэлтэд маань ихээхэн тус болсон. Энэ ажлын үр дүнг жишээ нь манай бусад нээлттэй эхийн бүтээгдэхүүнээс харж болно Горидж.

Олон PHP ажилчдад даалгавруудыг хуваарилах

Харилцааны механизмыг хэрэгжүүлсний дараа бид даалгавруудыг PHP процесс руу хэрхэн хамгийн үр дүнтэй шилжүүлэх талаар бодож эхэлсэн. Даалгавар ирэхэд програмын сервер үүнийг дуусгахын тулд үнэгүй ажилтныг сонгох ёстой. Хэрэв ажилчин/процесс алдаагаар дуусгавар болох эсвэл "үхэх" тохиолдолд бид түүнээс салж, солих шинийг бий болгоно. Хэрэв ажилчин/процесс амжилттай дууссан бол бид үүнийг ажил гүйцэтгэх боломжтой ажилчдын санд буцааж өгнө.

RoadRunner: PHP нь үхэхийн тулд бүтээгдээгүй, эсвэл Голанг нь аврахын тулд бүтээгдээгүй

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

Үүний үр дүнд бид хоёртын хэлбэрээр танилцуулсан аливаа хүсэлтийг боловсруулах чадвартай ажиллаж байгаа PHP серверийг хүлээн авлаа.

Манай програм вэб серверийн үүргийг гүйцэтгэхийн тулд бид ирж буй HTTP хүсэлтийг илэрхийлэх найдвартай PHP стандартыг сонгох шаардлагатай болсон. Манай тохиолдолд бид зүгээр л хувиргах Формат руу шилжихээс net/http хүсэлт PSR-7Ингэснээр өнөө үед байгаа ихэнх РНР фреймворкуудтай нийцдэг.

PSR-7 нь өөрчлөгддөггүй гэж үздэг (зарим нь техникийн хувьд тийм биш гэж хэлдэг) учраас хөгжүүлэгчид хүсэлтийг үндсэндээ дэлхийн байгууллага гэж үзэхгүй програм бичих хэрэгтэй болдог. Энэ нь урт хугацааны PHP процессуудын үзэл баримтлалд маш сайн нийцдэг. Одоогоор нэрлэгдэж амжаагүй бидний эцсийн хэрэгжилт дараах байдалтай байна.

RoadRunner: PHP нь үхэхийн тулд бүтээгдээгүй, эсвэл Голанг нь аврахын тулд бүтээгдээгүй

RoadRunner-ийг танилцуулж байна - өндөр хүчин чадалтай PHP програмын сервер

Бидний анхны туршилтын даалгавар бол API backend байсан бөгөөд энэ нь үе үе гэнэтийн хүсэлтийг (ердийнхөөс илүү олон удаа) мэдэрдэг. Ихэнх тохиолдолд nginx хангалттай байсан ч ачааллын өсөлтийг хангахын тулд системийг хурдан тэнцвэржүүлж чадаагүй тул бид 502 алдаатай байнга тулгардаг.

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

Жилийн дундуур бид шийдлээ сайжруулж, MIT лицензийн дагуу GitHub дээр нийтэлж, нэрлэсэн. Замчин, ингэснээр түүний гайхалтай хурд, үр ашгийг онцолж байна.

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.

дүгнэлт

Зарим хүмүүс PHP-ийг зөвхөн WordPress залгаас бичихэд тохиромжтой, удаан, төвөгтэй хэл гэж хуучирсан үзэл бодолд автсан хэвээр байна. Эдгээр хүмүүс PHP-д хязгаарлалт байдаг гэж хэлж магадгүй: програм хангалттай том болоход та илүү "боловсорч гүйцсэн" хэлийг сонгож, олон жилийн турш хуримтлагдсан кодын баазыг дахин бичих хэрэгтэй.

Энэ бүхэнд би хариулахыг хүсч байна: дахин бодоорой. Зөвхөн та PHP-д ямар нэгэн хязгаарлалт тавьж чадна гэдэгт бид итгэдэг. Та бүх амьдралаа нэг хэлнээс нөгөө хэл рүү үсэрч, өөрийн хэрэгцээнд тохирсон төгс тохирох хэлийг хайж олоход зарцуулж болно, эсвэл хэлийг хэрэгсэл гэж бодож эхэлж болно. PHP гэх мэт хэлний дутагдал нь түүний амжилтын шалтгаан байж болох юм. Хэрэв та үүнийг Go гэх мэт өөр хэлтэй хослуулбал зөвхөн нэг хэлээр хязгаарлагдахаас хамаагүй илүү хүчирхэг бүтээгдэхүүн бий болгож чадна.

Go болон PHP-ийг хослуулан ажиллаж байсан тул бид тэдэнд хайртай гэж хэлж болно. Бид нэгийг нь нөгөөгийнхөө төлөө золиослохоор төлөвлөөгүй, харин энэ хос стекээс илүү их үнэ цэнийг олж авах арга замыг эрэлхийлэх болно.

UPD: RoadRunner-ийг бүтээгч, анхны нийтлэлийн хамтран зохиогчийг бид угтаж байна - Лахесис

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх