Požadavek nečekající na odpověď
Školení, která pořádám
Pokud má být výsledkem požadavku na webový server spuštění nějaké dlouhotrvající operace, je vhodné alespoň rychle zobrazit nějakou hlášku, která o tom uživatele informuje. Jedno možné řešení spočívá ve vysypání výstupu s hláškou a pokud navíc potřebujeme, aby operace doběhla i v případě přerušení stahování stránky, tak jeho zabránění. Nevýhodou tohoto řešení je po celou dobu zobrazený ukazatel stahování stránky, který může některé uživatele iritovat.
Pokud by se jednalo o program příkazové řádky, nabízí se jeho spuštění s operátorem &
, který zajistí provedení na pozadí. PHP tento operátor podporuje při současném přesměrování výstupu např. do /dev/null
ale nepodporuje.
Ideálním řešením by bylo napsat si démona, který poběží stále a jen bude čekat na požadavky např. na socketu. To je ale poměrně pracné a navíc na většině webhostingů nerealizovatelné.
Dominik Fišer mě upozornil ještě na jedno možné řešení – dlouhotrvající operaci je možné napsat do samostatného skriptu, ten nechat spustit funkcí curl_multi_exec a nečekat na odpověď. Jednoduché, elegantní.
Diskuse
Non_E:
PHP samozřejmě podporuje spouštění shellových příkazů na pozadí klasicky ampersandem. V zaměstnání to tak děláme běžně. Jen je potřeba ošetřit stdout a stderr.
Viz
http://cz2.php.net/manual/en/function.exec.phpNote: If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.
Salko:
Ja osobne už nejaké 4 roky používam metódu, že pomocou fsockopen() otvorím port 80 (alebo nastavený port), vygenerujem normálnu HTTP požiadavku (GET alebo POST) a zatvorím spojenie, bez toho aby som čakal na odpoveď. V tejto požiadavke zavolám servisný PHP skript, ktorý ako prvý riadok ma funkciu ignore_user_abort(true);
Neviem či je to úplne podľa pravidiel, ale za ten čas som nemal žiaden problém a môžem vykonávať pomocné servisné skripty ktoré nijako nezdržujú užívateľov...
Prog.:
Myslím, že práve na takéto prasačinky sa hodí trocha ajaxu. Spojenie so serverom sa tak ani nemusí uzatvárať - môže byť celý čas aktívne a môžu sa po ňom priebežne zo servera posielať údaje o stave operácie...
Dundee:
Díky za zajímavý článek. O funkci ignore_user_abort slyším poprvé.
optik:
na dlouhotrvající věci nedoporučuji používat ani curl a ani cokoli jiné, kde na druhé straně bude váš apache, protože pokud máte vytížený server, tak ten dlouhotrvající proces se lehce může stát tím, který už bude navíc a zablokuje vám provoz ostatních normálních requestů. Lepší je rozhodně ten démon a netřeba vůbec psát vlastního, inetd bohatě postačí, pak jen to trochu zabezpečit a hotovo.
Andrew:
Pro nečekání na odpověď jsem dlouho s úspěchem používal curl_multi_exec. Nyní jsem přešel na nový server (nginx, curl 7.24 a PHP 5.5) a tento trik přestal fungovat. Čeká mě tedy zkoumání, co na to má vliv, ale pokud máte někdo nějaký tip, budu rád. :-)
Diskuse je zrušena z důvodu spamu.