Spíše bych to srovnal s daemontools, které spokojeně používám už dlouho
... proto většina mých démonu napsaných C++ dědí třídu ServiceApp, která sama umí zpracovat příkazy "start","stop","restart", "run" (foreground), takže aplikace je vlastně init scriptem. Navíc zvládne i spoustu dalších uživatelských příkazů, umí předat démonovi i další parametry na příkazové řádce a pokud něco démon vyplivne na stderr, tak se to přenese volajícímu do konzole (a nikoliv na stderr procesu init).
Démoni padaly, padají a padat budou, protože je nevytvářejí kyborgové, nýbrž lidé z masa a kostí a ti dělají chyby. Normální stav je že v OS existuje něco jako správce daemonů, který je spouští, zastavuje, atd. a sleduje jejich stav a pokud si to uživatel přeje, tak je v případě pádu i znovu nahodí. Linux v tomto normální není.
No pozor, odlište pád a výjimku. Jelikož jsem C++ programátor, tak pro mne je výjimka ošetřitelný stav, zatímco pád nikoliv. A pokud démon padá, tak první opravou je na místě pádu udělat test a vyhodit výjimku.
Ano Linux normální není, to je pravda. Samozřejmě, že pro Linux je ta třída implementovaná tak, že démona pustí jako forknutý child, a když ten child skončí, tak ho naforkuje znova. Ale není to žádná výhra, protože takhle může forkovat do nekonečna.
>> Normální stav je že v OS existuje něco jako správce daemonů, který je spouští, zastavuje, atd.
Jasně - třeba ve Windows. Tam je to vymyšleno suprově - zatímco když mám nějaký problém s daemonem pod Unixy, tak si ho prostě spustím normálně ručně v terminálu na popředí, zapnu si volby jaké chci a debuguju jako každý jiný proces, na Windows udělám co? Nejspíš na to budu zase muset mít nějaký SuperDuperMicrosoftServiceDebugger. Hurá.
Ale jinak hlavně, že je to "normální".
Když začne řádit OOM Killer, tak je snad lepší restartovat celý stroj. Jaký to má význam, pokud OOM Killer zabije démona, který se následně hned znova spustí, aby jej OOM Killer zase zabil?
Na světě je moc lidí, náhodně některé popravíme...
OOM Killer je big fail linuxu. Kéž by konečně byl linux schopen pořešit swap + kvóty na alokovanou paměť. Už asi chápu, proč naši admini raději strkaj každou službu do virtuálu :-)
> Když začne řádit OOM Killer, tak je snad lepší restartovat celý stroj. Jaký to má význam, pokud OOM Killer zabije démona, který se následně hned znova spustí, aby jej OOM Killer zase zabil?
To má smysl v případech kdy ten démon zblbnul tak že naalokoval neobvykle moc paměti.
> Na světě je moc lidí, náhodně některé popravíme...
OOM Killer rozhodně nefunguje náhodně.
> OOM Killer je big fail linuxu. Kéž by konečně byl linux schopen pořešit swap + kvóty na alokovanou paměť. Už asi chápu, proč naši admini raději strkaj každou službu do virtuálu :-)
Cgroups?
"To má smysl v případech kdy ten démon zblbnul tak že naalokoval neobvykle moc paměti"
V tom případě je to v pořádku, protože to je chyba, která musí být opravena. Ale radši bych, kdyby jádro žravým procesům začalo utahovat limity včas, aby démonovi začali lítat vyjimky OutOfMemoryException, než že bude sestřelen. Možná opravdu změnit alokační strategii.
Pro memory leaky je nejlepší právě swap. Ty se tam vesele odloží a pak už nikomu nechybí paměť :-)
Nicméně jsem měl s OOM Killerem už zkušenost a to takovou, kdy mi žravý adobe flashplayer vyžral paměť tak, že mi OOM sestřelil Eclipse i s rozdělanou prací. Možná že eclipse zabíral víc paměti, nevím, ale rozhodně to nebylo dobré řešení.
Třeba hodně pomůže to, že Windows nemá overcommit a autoři aplikací nepoužívají malloc na rezervaci adresového prostoru (fakt blbej nápad). Pak není problém vůbec řešit killování aplikací. Aplikace jednoduše dostane zamítnutý požadavek na další paměť. A jestli se kilne sama, nebo to vyřeší jinak je její problém.
Mimochodem, včera jsem si s tím hrál a na stroji bez swapu jsem vypnul overcommit. Výsledkem bylo, že mi nenaběhne ani Unity, protože si procesy rezervují stovky megabajtů a velice rychle tak vyčerpají volnou paměť, přestože ji nikdy nepoužijí.
No ptáš se nesmyslně, protože pokud není třeba zabíjet procesy kvůli nedostatku paměti, je zbytečný vědět, zda je proces žravý korektně či nekorektně.
Pokud máme v systému procesy, které sežerou většinu paměťi, že ostatní procesy už prakticky nemohou běžet, otázku, zda je to chyba nebo schválně musí zodpovědět člověk... Například nastavením limitů nebo vrácením programu autorovi k opravě.
Řešit to pomocí OOMK je blbost. Jak píšou na těchto stránkách:
¨
http://www.win.tue.nl/~aeb/linux/lk/lk-9.html
"Of course, the very existence of an OOM killer is a bug."
Nejde to, protože autoři aplikací používají malloc pro rezervaci adresového prostoru, což není totéž jako rezervace paměti. Ve Windows se to rozlišuje. Stránky se buď rezervují (RESERVED), nebo commitují (COMMITED). V režimu RESERVED se sice vedou ve stránkovém registru procesu, ale nic v nich není, nelze do nich zapisovat, ani číst, fyzicky neexistují. Jakmile ji aplikace potřebuje, provede na kterékoliv rezervované stránce COMMIT a tím dostane přidělenou paměť. A nebo taky ne, pokud OS nemá kde brát.
Jenže aplikace třeba kolem UNIT po startu zarezervuji stovky megabajtů, které reálně nikdy nepoužijí. Pravděpodobně tedy používají malloc jen pro rezervaci adresového prostoru. Bohužel to operačnímu systému nehlásí, takže ten nemůže tušit, zda zabraná paměť opravdu může být v budoucnu reálně potřebná.
ULimit je fajn, ale neumí nastavovat limit nějak chytře, třeba na základě aktuálního stavu paměti. Třeba bych chtěl, aby limit každé aplikace byl vztažen k aktuálně volné paměti. Třeba pokud si nastavím limit 80%, budu schopen jeden jedním procesem využít celých 80% a dalším procesem 80% ze zbývajících 20%. Ale takovouhle logiku v linuxu nenajdu.
Unity tu nemám, tak to nemůžu zkoušet. Tipuju, že si spíš vyrobí nějaké mmapy s MAP_NORESERVE (obdoba RESERVED ve Windows, ale s automatickým commitem), což se ale u vypnutého overcommitu ignoruje a stránky se stejně commitují.
Btw. pokud vypnete overcommit, je potřeba ještě poladit overcommit_ratio, protože ve výchozím nastavení aplikace mohou alokovat jenom 50 %. (Pokud nastavíte moc, může se spustit OOM killer, když dojde jaderná paměť nebo cache.)
overcommit_ratio určuje počet procent RAM, která může být zabraná při overcommit_memory nastavené na 2 (overcommit_memory nastavené na 0 používá heuristiku, na 1 povoluje neomezený overcommit), tedy total_commit = swap_size + (ram_size * overcommit_ratio / 100) — stále to neznamená, že ta paměť bude při mallocu či mmapu opravdu zabrána jako ve Windows, může v ní být třeba cache nebo file-backed mmap (oboje lze kdykoliv snadno zahodit). Pokud je overcommit_ratio nastavené pod cca 80 (aby zůstalo dost místa na jádro a buffery), k overcommitu (a tedy na OOM killer) nemůže dojít.
No, jádro se o to snaží, když je zapnutá heuristika, ale už ze samotného principu alokace paměti není možné mít něco jako nealokovanou zaručenou rezervaci a nezaručená rezervace je (alespoň v Unixu) totožná se žádnou rezervací, takže je celkem zbytečné něco explicitně rezervovat (autoři Unity se asi chtěli vybodnout na kontroly mallocu).
To je pravda. Ve FreeBSD je integrace nekterych veci udelana velice jednoduse a pritom funkcnce - jeden init script je nasymlinkovany na ruzne nazvy.
Napr. openvpn se nasymlinkuje na openvpn_x, openvpn_y, ... a pomoci tech symlinku se potom ovladaji ruzne instance openvpn.
Tohle by Supervizoru taky sluselo.
Monit umi to same, ale navic kontroluje nejenom jestli proces bezi, ale jestli taky dela to co ma (reaguje na sitove requesty), nezere moc CPU (napr. zacykleni) ani pameti (napr. memory leak).
Napr. konfigurace pro Apache, ktera restartuje apache pokud spadne, kontroluje zda odpovida na requesty, kontroluje vyuziti CPU a pameti:
check process apache with pidfile /var/run/httpd.pid
start program = "/etc/init.d/httpd start"
stop program = "/etc/init.d/httpd stop"
if failed port 80 protocol http then restart # testovani http://127.0.0.1:80
if totalcpu usage > 75% then alert # soucet cpu usage vsech apache children
if totalmemory > 75% then alert # soucet memory usage vsech apache children
To je sice pravda, ale je pouziti scriptu pro start misto vlastniho fork+exec opravdu problem?
To jestli se pouzivaji pro start/stop sluzeb init scripty (nebo upstart/systemd/daemontools apod. start+stop metody) je celkem irelevantni - podstatne je jestli je monitorovaci system schopny detekovat ze dana sluzba nebezi a opravit ji - ne jestli ji nastartuje prostrednictvim nejakeho externiho scriptu nebo primo pomoci fork+exec.
Vyhodou Monitu je, ze krome situace kdy sluzba nebezi protoze daemon spadnul umi detekovat i stavy kdy bezi ale nechova se normalne. Umi tak predchazet vice chybam nez jina reseni.
Monit umi krome procesu hlidat dalsi veci - system load, system memory+swap usage, disk usage, atd. a provazat sluzby zavislostmi => napr. pokud se naplni filesystem kde jsou ulozena data dane sluzby a ta kvuli tomu prestane fungovat, umi na to upozornit , nebo spustit script ktery se pokusi filesystem vycistit - odstranit docasne soubory, apod. a sluzbu tak znovu rozbehnout. Pokud supervizor monitoruje jen existenci procesu a ten dal bezi i kdyz kvuli plnemu filesystemu nefunguje, supervizor nezahlasi zadnou chybu (Monit naproti tomu zjisti je proces nefunguje spravne i bez monitorovani filesystemu - diky protocol testu dane sluzby).
Dalsi vyhodou Monitu je, ze vyuziva minimum zdroju (je napsany v C) a ma minimum zavislosti - da se slinkovat staticky a pak potrebuje jen libc. Supervizor je napsany v python a stava se tak daleko vice pro vlastni funkci zavisly na externich knihovnach - pokud se napr. nektera z prerequisite knihoven nebo python "rozbije" (napr. nepovedeny upgrade, bug, apod.), pak supervizor sam muze byt problemem postizen a monitorovani se zastavi. Monit naproti tomu pobezi dokud se nerozpadne cely system (samozrejme pokud neni bug v samotnem Monit a z praxe je velmi stabilni).
Omlouvam se ze jsem s apache nedal zrovna nejlepsi priklad - Monit init scripty take nepotrebuje (v pripade apache se to byla celkem logicka volba).
Priklad pro Monit bez init scriptu:
check process django matching "manage.py"
start program = "/usr/bin/python /home/user/djangoproject/manage.py runserver" as uid cx and gid cx
v tejto suvislosti stoji za zmienku:
http://cr.yp.to/daemontools.html