Úlohy v PHP
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Úlohy v PHPÚlohy v PHP

 

Úlohy v PHP

Google       Google       1. 9. 2008       41 569×

Mnozí z vás se jistě již setkali s problémem, jak spustit nějaký skript, vykonat nějakou práci – úlohu – v určitý čas. V tomto článku si shrneme některé možnosti řešení.

Potřeba vykonat nějakou činnost v určený čas je u dnešních webových dynamických aplikací velice častá. Jako příklad můžeme uvést vyčištění cache, pročištění session přihlášení uživatelů, provedení zálohy, v dnešní době, kdy jsou v módě „webové hry“ (hromadné většinou tahové většinou strategické hry, k jejichž hraní stačí pouze internetový prohlížeč), taky tzv. „přepočty“. Ve všech prozatím jmenovaných příkladech se jedná o opakující se činnosti, ale taky se zde samozřejmě mohou vyskytnou i „jednorázovky“– kupř. naplánované vydání článku v určitou hodinu. Nazývejme takové činnosti „úlohami“. (Pozn.: Nejpřesněji by tyto činnosti asi vystihoval termín „naplánované úlohy“, ale ten si bohužel už zabraly Windows, proto pouze „úlohy“.)

Prvně tedy můžeme tyto úlohy rozdělit na opakující se a jednorázové. Opakující se, jak plyne z názvu, v pravidelných intervalech či časech vyvolávají znova a znova. Jejich využití je tedy hlavně na úlohy, jejichž časy spouštění na začátku naplánujeme, necháme je, aby dělaly svou práci, a staráme se o ně většinou jen tehdy, nedělají-li to, co se od nich očekává. Na druhou stranu, u jednorázových se většinou jedná o to, že v daný čas bychom nemohli danou činnost vykonat. Nebo prostě slouží jako ulehčení, abychom se nemuseli činností již dále zabývat – určíme její čas provedení a ona v ten čas bude provedena.

Ovšem pokud si uvědomíme, že webové aplikace jsou postaveny na architektuře klient-server, zjistíme, že úloha vlastně nemusí být provedena přesně v daný čas. Naše aplikace běží na vzdáleném serveru a do té doby, než přijde nějaký požadavek, je nečinná – což znamená, že její stav se nemůže nijak změnit. Změny se dočkáme teprve tehdy, když nějaký ten požadavek přijde.

Zde se možnosti vykonávaní úloh rozdělují na „bezprostředně vykonávané úlohy“ a „odložené úlohy“. První typ potřebuje, aby ke klientu a serveru přibyla ještě další entita, která si bude hlídat čas a spustí úlohu přesně v čas, kdy je potřeba. K tomuto způsobu vykonávání úloh se řadí cron a webcron, kdy každý je založen na trochu jiném principu, ale v základě jsou stejné.

Odložené úlohy naopak využívají faktu, že stav není potřeba měnit, dokud na aplikace nepřijde nějaký požadavek. Po příchodu požadavku aplikace nejdříve zjistí, jestli v čase mezi předchozím požadavkem a tím nynějším měly být vykonány nějaké úlohy a jestli ano, vykoná je. Teprve potom se zabývá zpracováním samotného požadavku. V obou případech přístupu k úlohám je zajištěno, že požadavek bude zpracován teprve po tom, co byly vykonány všechny úlohy, které předcházely požadavku. Jediné, co se bude lišit, je čas samotného vykonání úloh.

Cron

Cron je démon používaný v systémech unixového typu ke spouštění shellových příkazů v určitý čas. Ve Windows se nepoužívá cron, ale tzv. „Naplánované úlohy“. První cron byl velice jednoduchý program. Byl spouštěn při vstupu systému do víceuživatelského režimu. Celý program sestával z nekonečné smyčky:

  1. přečti konfigurační soubor (tzv. „crontab“)
  2. zjisti, jestli je v tento čas nějaký skript ke spuštění, případně takový spusť
  3. uspi se na jednu minutu
  4. a všechno zase od začátku

Jelikož většina serverů je založena právě na nějakém unixovém systému, je cron, pokud ho hosting podporuje, dobrou volbou pro spouštění úloh. Ovšem je zde problém, že asi jen na málokterém (nejspíš na žádném) hostingu vám nedovolí přímý zápis a možnost editace crontabu, proto jen těžko jde spravit vlastní zadávání úloh. Záleží, jaké možnosti pro editaci úloh v crontabu hoster dovolí. Řešení vlastního hostingu také nemusí být ideální. Ale výhodou je, že skripty, které serverový cron spouští, vůbec nemusí být přístupné pro vnější svět.

Webcron

Webcronem je míněna služba, která poskytuje možnost, jak z jiného umístění nechat vykonat nějaký skript. Prakticky je to většinou realizované tou nejjednodušší cestou – na serveru webcronu je cron, který v daný čas vyšle HTTP požadavek na zadanou adresu úlohy. Jak je vidět, opět se jedná o možnost, jak vykonávat úlohy, jak na ně má přijít čas.

Problémem webcronu ale je, že úlohy musí být přístupné přes HTTP, což nemusí být zrovna bezpečné – každý si může vyslat požadavek serveru, čímž aktivuje úlohu. Dá se tomu předcházet např. kontrolou dat předaných v požadavku, ale ani to není 100% – dají se napodobit, podstrčit. U některých úloh třebas nemusí vadit, že se vykonají předčasně či vícekrát (např. u toho vyčištění cache by to nemuselo být zas tak hrozné), u jiných to už může být problém (např. ty „přepočty“ u webových her). Také je zde problém s tím, že pokud server poskytovatele webcronu spadne, úlohy nebudou vykonány. A pokud webcron neposkytuje nějaké API, které by přidávání úloh zjednodušovalo, zůstává to prakticky stejné jako u normálního cronu.

Odložené úlohy

Jak již bylo popsáno, odložené úlohy se vykonávají teprve až přijde na aplikaci nějaký požadavek. Mezitím mohou někde ležet. Většinou jako takovéto úložiště slouží databáze, ale mohou to být i soubory, může to být třeba i vlastní crontab.

Odložené úlohy mají oproti cronu i webcronu výhodu, že nepotřebují, aby je někdo spouštěl. Spustí se samy, pokud přijde nějaký požadavek (lépe řečeno při každém požadavku musíme kontrolovat, jestli nejsou nějaké úlohy k vykonání a případně je spustit; ale tato činnost se dá dosti zautomatizovat). Mají tedy výhodu v tom, že se aplikace nemusí spoléhat na nic dalšího. Háček tkví v tom, že server dnes snad vždy postaven konkurenčně – může obsluhovat více požadavků naráz. Pokud na aplikaci přijde více požadavků najednou, může dojít k tomu, že by se některá úloha mohla provést vícekrát (což hrozí hlavně u „dlouhotrvajících úloh“ a/nebo velkém náporu návštěvníků).

Ukázka implementace odložených úloh

Abychom nezůstali jen u suché teorie, ukážeme si jednu možnost implementace odložených úloh. Bude se jednat o jednoduchou třídu zastřešující práci s úlohami a jejich inicializaci, k vytváření vlastních úloh, které budou dělat něco prospěšného, budeme naši třídu specializovat (neboli z ní budou konkrétní úlohy dědit). K ukládání bude sloužit databáze, ke které se budeme připojovat pomocí PDO. Stáhněte si zdrojové kódy s příklady.

Pro začátek si napíšeme nějakou jednoduchou úlohu, např. na promazávání cache:

<?php
final class ClearCache extends Task
{
    protected function execute()
    {
        list($cache_dir) = $this->getParameters();

        $mode = fileperms($cache_dir);

        $this->deleteDirectory($cache_dir);

        mkdir($cache_dir, $mode);
    }

    private function deleteDirectory($dir)
    {
        foreach (glob($dir . '/*') as $item) {
            if (is_dir($item)) {
                $this->deleteDirectory($item);
            } else {
                unlink($item);
            }
        }

        rmdir($dir);
    }

    protected function areParametersValid()
    {
        $params = $this->getParameters();

        if (count($params) == 1 && is_dir($params[0])) {
            return true;
        }

        return false;
    }
}

Řekl bych, že kód je samovysvětlujicí. Metoda execute() je v rodičovské třídě deklarovaná jako abstraktní – dědící úlohy pak tuto metodu implementují svým funkčním kódem. Zde je to jasné – smaže se celá složka s cacheí a poté se vytvoří nově.

Další metodou, kterou zde můžeme vidět, je areParametersValid(), ve které, jak název napovídá, je umístěn kód pro zkontrolování platnosti předaných parametrů. My chceme pouze jeden a chceme, aby to byla složka.

Úlohu pak můžeme vytvořit jednoduše pomocí:

<?php
$task = new ClearCache(strtotime('+1 minute'), 'cache');

Ovšem problém je, že takto vytvořená úloha prostě vznikne a zanikne, nikam se neuloží, nikdy se neprovede. Proto musíme vytvořit pro úlohy nějaký úložný prostor (je potřeba vytvořit nejdříve tabulku v databázi) a nově vytvořenou úlohu tam uložit. Uděláme to jednoduše pomocí:

<?php
Task::setStorageWrapper(new PDOStorageWrapper(DB_DSN, DB_USER, DB_PASSWD));

$task->store();

Úloha je vytvořena i uložena. V aplikaci pak můžeme říct, aby se úlohy vykonaly:

<?php
Task::processUndone();

Tak a to je všechno, nic víc potřeba dělat není. Pro více příkladů se podívejte do archivu se zdrojovými kódy. Vylepšení by se avšak dalo udělat mnoho. Největší problémy určitě dělá ta synchronizace při více přístupech naráz. Také by určitě stálo za zvážení použít nějaký lepší způsob sdílení init() funkcí (viz zdrojové kódy a příklady). Hodila by se jistě podpora opakovaných úloh (ano, ta chybí). Teď se to dá řešit tak, že úloha ve svém těle (v metodě execute()) vždycky vytvoří znovu sama sebe (samozřejmě s jiným časem), ale určitě by to šlo vyřešit lépe.

Shrnutí

Způsobů, jak v PHP spouštět úlohy, je více a výběr toho správného záleží na dané situaci. Možná je také kombinace všech způsobů dohromady. Na opakující se úlohy se nejvíce hodí cron – je na to prostě stavěný, navíc nabízí velice široké možnosti nastavení opakování (např. se může určit, že úloha se spustí vždycky první pátek v měsíci, či každý pátek třináctého atp.). Hlavní využití odložených úloh bych viděl v těch „jednorázovkách“. Ale problém je, pokud se takové úlohy nahromadí. Když se nastaví čas provedení více úloh na nějakou noční hodinu, tak to odnese první návštěvník, který si bude muset ráno počkat trochu déle, než se všechny provedou. Tady může pomoci webcron, který v pravidelných intervalech (např. přes noc každou jednu hodinu) provede na aplikaci HTTP požadavek, čímž se úlohy vykonají.

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

Hlasování bylo ukončeno    
0 hlasů
Google
(fotka) Jakub KulhanAutor momentálně studuje na osmiletém gymnáziu v Kralupech nad Vltavou. Programování se věnuje od 11 let, kdy ho poprvé uchvátila možnost "mít vlastní stránky". Nakrátko poté objevil PHP a už se to s ním "vezlo". Webové aplikace zůstaly jeho hlavní doménou, ale ve svém volném čase probádává nejrůznější zákoutí světa programování, programovacích jazyků a všeho kolem nich.
Web    

Nové články

Obrázek ke článku Hybridní inteligentní systémy 2

Hybridní inteligentní systémy 2

V technické praxi využíváme často kombinaci různých disciplín umělé inteligence a klasických výpočtů. Takovým systémům říkáme hybridní systémy. V tomto článku se zmíním o určitém typu hybridního systému, který je užitečný ve velmi složitých výrobních procesech.

Obrázek ke článku Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Vedení týmu v oboru informačních technologií se nijak zvlášť neliší od jiných oborů. Přesto však IT manažeři čelí výzvě v podobě velmi rychlého rozvoje a tím i rostoucími nároky na své lidi. Udržet pozornost, motivaci a efektivitu týmu vyžaduje opravdu pevné manažerské základy a zároveň otevřenost a flexibilitu pro stále nové výzvy.

Obrázek ke článku Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Za poslední rok se podoba práce zaměstnanců změnila k nepoznání. Především plošné zavedení home office, které mělo být zpočátku jen dočasným opatřením, je pro mnohé už více než rok každodenní realitou. Co ale dělat, když se při práci z domova ztrácí motivace, zaměstnanci přestávají komunikovat a dříve fungující tým se rozpadá na skupinu solitérů? Odborníci na personalistiku dali dohromady několik rad, jak udržet tým v chodu, i když pracovní podmínky nejsou ideální.

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý