Професионална програма
Loading...
+ Нов въпрос
SvetlinYotov avatar SvetlinYotov 7 Точки

Async задачи в PHP

Привет :)

Работя върху система, която автоматично да извършва задачи, които понякога може да отнемат доста време от порядъка на 20 и повече секунди. Няма да е ок потребителят да седи на страницата докато му се показва някакъв loadbar, а и задачите, които ще се извършват от сървъра няма да са пряко свързани с потребителя. 

И се чудя дали е възможно да се реализира подобна функционалност с php: потребителят изпраща заявка на сървъра, че иска да направи нещо и сървъра връща отговор: "ок, заемам се"; след което сървъра започва да работи върху изпратената от потребителя задача. Ако юзера иска да провери до каква степен от изпълнението на заявката е стигнал сървъра, праща заявка на която сървъра връща само процент на това колко от задачата е свършил. А когато сървъра свърши със задачата, просто вдига един флаг в БД, че е готов.

Тази функционалност наподобява малко на youtube, където може да пуснеш заявка, че искаш да си направиш видеото черно бяло например. Но няма да седиш и да чакаш отговор от сървъра, а тази задача се изпълнява отзад, а потребителя само вижда до каква степен на завършеност на задачата е стигнал сървъра. Горе долу ми трябва подобна функционалност само дето няма да обработвам видео. :)

Тагове:
0
PHP Web Development Basics
RoYaL avatar RoYaL Trainer 6847 Точки
Best Answer

Краткият отговор е - не може.

Дългият отговор обаче съвсем не носи същото послание. При нормално компилиране езикът на поддържа такава функционалност, но може да бъде компилиран с определени флагове, съответно тази функционалност да бъде отключена или да бъде симулирана по някакъв начин.

Езикът не поддържа синтактична захар като await и async, но поддържа пускане на задачки ръчно на различни нишки, подобно на използването на Thread, Runnable, etc.. в Java. Всъщност това са стандартнитe pthreads

Има малък catch в цялата работа и загатнах за него по-горе. Трябва компилираните байнърите от сорс да са с флагове позволяващи Zend Thread Safety. Виж секцията Requirements

Това е PECL пакет, така че ще трябва да го изтеглиш от пакетите там. Погледни секция Installation. Има нова уловка за Windows.

Това идва и със своите недостатъци, разбира се. Ако решиш да смениш версията на РНР, ще трябва отново да изтеглиш сорс код и да го компилираш ръчно. Няма да можеш да се възползваш и от дефолтенр package manager на някоя от линукс дистрибуциите, тъй като по подразбиране ще ти свали binary, което не е Zend Thread Safe. Така, че поемеш ли по този път - това, което ще се случи е да разчиташ само на себе си.

Алтернатива на това е да симулираш многонишково поведение. Което не е толкова ефективно, разбира се, тъй като няма да натоварваш процесора като такъв, а операционната система - с допълнителни процеси. Т.е. това, което можеш да направиш е за всяка отделна задачка, която искаш да се изпълни паралелно, да spawn-неш нов процес. РНР има богата библиотека за работа с процеси - можеш да създадеш процес от родителски процес чрез fork(). Да отвориш нов процес с proc_open() и да пренасочваш техните входно-изходни операции по pipe-ове чрез референтен аргумент за възможните pipe-ове.

Хвърли едно око и на готова работна рамка за това - Gearman

Погледни и клиентска библиотека, която може да комуникира с твоите асинхронни процеси или по-скоро обратното, така наречените Server-sent events

Поздрави,

Иван

3
19/02/2016 00:44:15
SvetlinYotov avatar SvetlinYotov 7 Точки

Благодаря ти много за предложенията! smiley

А възможно ли е да се направи и с cron или няма да е толкова ефективно. Идеята ми е да върви един крон, който всяка минута да проверява за нови записи в таблица в БД, в която таблица ще се добавя запис, когато потребителят поиска да пусне background задача, като съответните необходими параметри ще бъдат в различни колони. И крон-а като види, че има нов запис в таблицата, взимам му параметрите, слага един флаг че се работи върху съответния запис в базата (за да не го хване същото нещо следващия крон). И крон-а като си свърши работа вдига още един флаг на съответния ред от базата, от който е взел параметрите, че е готово.

Това може ли да се приеме като ефективно решение, ако приемем, че не е критично за workflow-a ако не се започне изпълнението на beckground task-a в момента, в който потребителя прати заявката за начало на задачата.

0
RoYaL avatar RoYaL Trainer 6847 Точки

Да, разбира се, кронът е просто начин на определени интервали да spawn-неш процеси от операционната система. Това, което ще направи кронът е да spawn-не php процес, който да интерпретира определен .php файл. Същото ще постигнеш и с proc_open :) Направо го както ти е по-удобно щом не е критично натоварването, тъй като кронът на всяка минута със сигурност е по-затормозяващ :)

1