Loading...
SvetlinYotov avatar SvetlinYotov 7 Точки

Async задачи в PHP

Привет :)

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

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

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

Тагове:
0
PHP Web Development Basics
RoYaL avatar RoYaL Trainer 6849 Точки
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 6849 Точки

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

1
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.