Nagy terhelésű rendszerek fejlesztése 2.
Mielőtt a bevezető cikk után rátérnénk a konkrét load balancing és clusterező megoldásokra, szeretnék egy jelentéktelennek tűnő, ám de annál hasznosabb eszközt bemutatni. Hölgyeim és uraim, konzolokat elővenni, debuggereket bekapcsolni, háttérfolyamatokat írunk.
A sorozatban megjelent
- Nagy terhelésű rendszerek fejlesztése 1. – Alkalmazás-evolúció
- Nagy terhelésű rendszerek fejlesztése 2.
- Nagy terhelésű rendszerek fejlesztése 3.
- Nagy terhelésű rendszerek fejlesztése 4. – Üzemeltetés
Bár sokan állítják, hogy webes nyelv, és ezért nem alkalmas daemonok, háttérfolyamatok kezelésére, ezúttal PHP-ban fogunk tevékenykedni. Ahhoz, hogy a példákat ki tudd próbálni, szükséged lesz egy sockets, pcntl és posix kiegészítőkkel lefordított PHP-ra, valamint egy Linux konzolra. Ha esetleg nem lenne ilyen kéznél, tölts le egy Ubuntu Linuxot, és telepítsd föl mondjuk Microsoft Virtual PC-be. (Macesek: az OS X konzolja feltehetőleg megfelel a célnak, pusztán a PHP-t kell telepíteni.)
Előre felhívom mindenki szíves figyelmét, hogy az itt leírt technikákat lehetőleg ne a céges vagy egyetemi szerveren próbálgassa! Én szóltam!
A Linux processz modell
Mivel alapvető igény egy háttérfolyamatnál, hogy több feladatot is el tudjon végezni egyszerre, ismerkedjünk meg a processzekkel. Amióta léteznek multitasking operációs rendszerek (és ez már nem ma kezdődött), ezek tudnak a feladatok között váltani. A feladatok különálló, úgynevezett virtuális memóriatérrel rendelkeznek, ami a mindenkori elvi maximális memória mérete (32 biten ez 4 GB). Ezen a memóriaterületben dolgozhatnak a folyamatok.
Mellékesen megjegyezném, hogy ennek a memóriának nem kell rendelkezésre állnia, hiszen az operációs rendszer képes az éppen nem használt lapokat (pages) kirakni a merevlemezre. Ezt a folyamatot hívjuk swapelésnek vagy page-elésnek.
Visszatérve a folyamatokra: a POSIX (Unix) világban a folyamatoknak van szülőfolyamata. Ha egy processz szeretne egy másikat indítani, azt csak úgy tudja, hogy saját magából „klónoz” egyet, azaz kettéválik, és mind a két fél rendelkezni fog a virtuális memória egy-egy másolatával és valamennyi megnyitott fájlleíróval. Ezt a folyamatot hívjuk forkolásnak.
A harmadik számunkra fontos aspektus a signalok kérdése. A processzek küldözgethetnek egymásnak signalokat, és el is kaphatják azokat. Különösen fontos, hogy amennyiben egy gyermekfolyamat terminál, a szülőfolyamat automatikusan kap egy SIGCLD
signalt, avagy egy értesítést. A gyermekfolyamat mindaddig úgynevezett zombi állapotban marad, amíg a szülő le nem kezeli a signalt.
Signalok a gyakorlatban
Hogy ennek a sok elméletnek adjunk egy kis gyakorlati alapot is, lássunk egy példakódot signal handlingre:
#!/usr/bin/php
<?php
/**
* PHP 4.3.0 ota csak igy mennek a signalok. Az
* interpreter nem szakitja meg kozvetlenul a futast,
* hanem N parancsonkent megnezi, volt-e signal.
*/
declare(ticks = 1);
/**
* Ez lesz a signal handlerunk.
*/
function sig_handler($signo) {
echo('Caught signal: ' . $signo . "\n");
}
/**
* Beallitjuk, hogy a SIGINT-et kapjuk el.
*/
pcntl_signal(SIGINT, 'sig_handler');
/* Csinalunk valamit, amit meg lehet szakítani. */
while (1) {
echo('Sleeping for one second...\n');
sleep(1);
}
echo('Terminating...\n');
/* Rendes exit koddal lepunk ki */
exit(0);
Ahhoz, hogy ezt a programot el tudjuk indítani, chmod
-dal rá kell tennünk az execute jogosultságot, például így:
chmod 0750 signaldemo.php
Ha magát a kódot elindítjuk, tapasztalni fogjuk, hogy Ctrl+C-vel nem lehet kilépni belőle. Ez annak köszönhető, hogy az említett billentyűkombináció a SIGINT signalt küldi, amit az alkalmazásunk elkap.
Ha már ennyit beszéltünk róluk, nézzünk egy listát a fontosabb signalokról:
ALRM
(alarm): Azt jelzi, hogy egy előre beállított időzítő lejárt. Ezt használhatjuk aszinkron időzítésre.HUP
(hangup): Azt jelzi, hogy a a szülőfolyamat bezárta a terminált. Ha nem kapjuk el, a program bezárásához vezet. Egyébként a modemes időkből származik.INT
(interrupt): Megszakítás, Ctrl+C. Ha nem kapjuk el, a program bezárásához vezet.TERM
(terminate): Megkéri a programot, hogy fejezze be a működését. Elkapva van lehetőségünk befejezni az aktuális munkát.KILL
: A program azonnali bezárását eredményezi, nem lehet elkapni.CHLD
(child): Egy gyerekprocessz terminált, és várja a feldolgozást.
A részletes lista megtalálható a kill
parancs kézikönyv oldalán vagy a PHP doksiban. (A kézikönyvet a man kill
parancs kiadásával lehet megtekinteni.)
Forkoljunk
Na, tisztába tettük a signalokat, forkoljunk. (Alkalomadtán ellőhetjük a gyengus „Ne fhorkoljál már…” poént is.)
A fork parancs PHP-ban pcntl_fork()
néven fut. Mint már említettük, a teljes memóriaterület másolásra kerül, tehát a nyitva hagyott állományleírókat, adatbázis kapcsolatokat stb. célszerű forkolás előtt vagy azt követően a keletkező gyerekprocesszben bezárni. (Attól, hogy a gyerekben bezárjuk a szülőben még nyitva marad a kapcsolat.)
A fork
parancs úgy működik, hogy visszaad egy int
típusú változót, ami a következő értékeket veheti fel:
- -1: ha nem sikerült a fork. Ennek oka lehet pl. az, hogy elfogytak a folyamatazonosítók (lásd: fork bomb).
- 0: sikerült a fork, a gyermekfolyamatban vagyunk.
- >0: sikerült a fork, a szülőfolyamatban vagyuk. A visszakapott érték a gyermekfolyamat
PID
-je (process id) lesz. Ezzel tudunk rá hivatkozni pl. egy esetlegeskill
parancsnál.
A zombi folyamatok kezelésére két lehetőség van. Vagy használjuk a pcntl_waitpid()
parancsot, és megadjuk paraméterül a konkrét PID
-et amit várunk, vagy használjuk signal handlerben a pcntl_wait()
parancsot. Ez abban az esetben hasznos, ha több gyereket indítunk, és nem tudjuk melyik fog előbb terminálni. Fontos figyelembe venni, hogy egy SIGCLD
signal jelentheti több gyermekfolyamat terminálását is, ezt le kell kezelnünk.
Ezzel a tudással fölfegyverkezve írjunk egy olyan programot, ami elindít tíz gyermeket, a gyermekek pedig végrehajtanak öt feladatot.
#!/usr/bin/php
<?php
/**
* PHP 4.3.0 ota csak igy mennek a signalok. Az
* interpreter nem szakitja meg kozvetlenul a futast,
* hanem N parancsonkent megnezi, volt-e signal.
*/
declare(ticks = 1);
$maxchildren = 5;
$children = array();
$terminate = false;
$parent = true;
/**
* Allitsuk be a signal handlereket a syscallok ujrainditasaval
*/
pcntl_signal(SIGTERM, 'handle_term', true);
pcntl_signal(SIGCLD, 'handle_child', true);
/**
* Irjuk ki az uzeneteket a PID-jukkel egyutt
*/
function logMessage($message) {
echo('[' . posix_getpid() . '] ' . $message . "\n");
}
/**
* Kezeljuk a gyerekek terminalasat
*/
function handle_child($signo) {
global $children;
/**
* Kerjuk le a terminalt gyerekek PID-jeit.
* A WNOHANG azt jelenti, hogy ha nincs gyerek,
* akkor ne varakozzon.
*/
while (($pid = pcntl_wait($status, WNOHANG)) > 0) {
unset($children[$pid]);
logMessage('Child terminated: ' . $pid);
logMessage('Current active workers: ' . count($children));
}
}
/**
* Kezeljuk le a TERM signalt.
*/
function handle_term($signo) {
global $terminate;
logMessage("Caught SIGTERM...");
/**
* Mivel a szkriptnyelvek inkabb a kollaborativ multitaskingot
* tamogatjak, csak beallitjuk a flaget, es megvarjuk hogy a
* fociklus kezelje a helyzetet.
*/
$terminate = true;
}
/**
* Fuggveny a gyerekprocesszek munkajahoz.
*/
function work() {
global $terminate;
/**
* Varialjuk egy kicsit a feladatok szamat...
*/
$maxtask = rand(2, 10);
for ($i = 0; $i < $maxtask; $i++) {
if (!$terminate) {
logMessage('Executing task ' . $i . '...');
sleep(1);
} else {
logMessage('Got termination request!');
break;
}
}
}
/**
* Iteraljunk a vegtelensegig ha a szulofolyamatban vagyunk,
* es nem erkezett terminalasi keres.
*/
while (!$terminate && $parent) {
logMessage('Current active workers: ' . count($children));
/**
* Ha szukseg van uj gyermekekre a szuloben...
*/
while(!$terminate && $parent && (count($children) < $maxchildren)) {
$pid = pcntl_fork();
if ($pid == -1) {
logMessage('Fork failed!');
} else if ($pid == 0) {
$parent = false;
logMessage('Worker started...');
work();
logMessage('Worker finished...');
} else {
$children[$pid] = $pid;
logMessage('Child ' . $pid . ' started...');
logMessage('Current active workers: ' . count($children));
}
}
if (!$terminate && $parent) {
sleep(5);
}
}
if ($parent) {
/**
* Minden meg futo gyereknek szoljunk, hogy
* legyen kedves terminalni.
*/
logMessage('Terminating ' . count($children) . ' children...');
foreach ($children as $child) {
logMessage('Terminating ' . $child);
posix_kill($child, SIGTERM);
/**
* Megadjuk a tickelheto fuggvenyhivast...
*/
sleep(2);
}
/**
* Ha meg van futo gyerek akkor most mar erelyesen
* szoljunk ra.
*/
logMessage('Killing ' . count($children) . ' children...');
foreach ($children as $child) {
logMessage('Killing ' . $child);
posix_kill($child, SIGKILL);
}
}
exit(0);
Ha ezt elindítjuk, látható hogy a szülőfolyamat mindig gondoskodik arról, hogy legyen megfelelő mennyiségű worker a feladatok elvégzéséhez. SIGTERM
-re értesíti a gyerekeket, és mindegyiknek ad két másodpercet hogy termináljon. (Ez a ticks működés miatt szükséges.)
A program működését a ps af
paranccsal ellenőrizhetjük:
5086 pts/1 Ss 0:00 /bin/bash
17763 pts/1 S+ 0:00 \_ /usr/bin/php ./forkdemo.php
17768 pts/1 S+ 0:00 \_ /usr/bin/php ./forkdemo.php
17771 pts/1 S+ 0:00 \_ /usr/bin/php ./forkdemo.php
17777 pts/1 S+ 0:00 \_ /usr/bin/php ./forkdemo.php
17778 pts/1 S+ 0:00 \_ /usr/bin/php ./forkdemo.php
17779 pts/1 S+ 0:00 \_ /usr/bin/php ./forkdemo.php
Csatlakozzunk le a terminálról
Ez eddig szép és jó, de megfigyelhető volt az, hogy a terminálon nyitva maradt a programunk. Ha becsukjuk a futtató terminált, megy a levesbe az egész. Mivel ez nem cél, tanuljunk meg lecsatlakozni a processzt nyitó terminálról. Miután a lecsatlakozás után már nem fog rendelkezésre állni az STDOUT
, amire írhatnánk az üzeneteket, először is át kell írnunk a logMessage()
függvényünket, hogy syslogot használjon:
openlog('php', LOG_NDELAY | LOG_PID, LOG_USER);
function logMessage($message) {
syslog(LOG_DEBUG, $message);
}
Most, hogy ezt megugrottuk, nézzük a feladat lényegi megoldását: először is forkolunk egyet, majd a szülőben terminálunk, a gyerekben pedig megkérjük az operációs rendszert, hogy mi lehessünk az ún. session leader, azaz legyen saját munkamenetünk. Ezt követően pedig becsukjuk az STDIN
és STDOUT
állományleírókat. A gyakorlatban mi sem egyszerűbb:
#!/usr/bin/php
<?php
openlog('php', LOG_NDELAY | LOG_PID, LOG_USER);
function logMessage($message) {
syslog(LOG_DEBUG, $message);
}
/**
* Forkoljunk
*/
$pid = pcntl_fork();
if ($pid == -1) {
logMessage('Detach failed!');
exit(1);
} else if ($pid > 0) {
exit(0);
}
/**
* Kerjuk el a session ID-t
*/
$session_id = posix_setsid();
if (!$session_id) {
logMessage('Detach failed!');
exit(1);
}
/**
* Lepjunk ki a konyvtarbol hogy ne fogjuk azt
*/
if (!chdir('/')) {
logMessage('Detach failed!');
exit(1);
}
/**
* Zarjuk be az allomanyleirokat
*/
$fh_std = array(STDIN, STDOUT);
foreach ($fh_std as $fh) {
if (!fclose($fh)) {
logMessage('Detach failed!');
exit(1);
}
}
sleep(120);
exit(0);
Ha most bezárjuk a terminált, és egy másikon megnézzük a ps af
parancsot, látni fogjuk, hogy a programunk ott maradt a háttérben. Ezzel kikerültük az olyan hackeket, mint a screen
-ben való indítgatás és társai.
Socket-kezelés
Ahhoz, hogy tudjunk a külvilággal beszélgetni, több megoldást is választhatunk. Olvashatunk adatbázisból, értekezhetünk signalokon keresztül, de ha adatot szeretnénk mozgatni, akkor az egyetlen működőképes technika a socket kezelés. A socket az, amivel többek között hálózati adatforgalmat is lehet bonyolítani, de ugyanolyan jól lehet file socketen keresztül beszélgetni egy másik folyamattal.
Szerveroldalon a socket-kezelésnek a következő fázisai vannak:
- Socket létrehozása:
socket_create()
- Bindolás egy címre:
socket_bind()
- Listen parancs kiadása:
socket_listen()
- Csatlakozó kliensek fogadása:
socket_accept()
- Kommunikáció:
socket_read()
éssocket_write()
- Socket zárása:
socket_close()
A mintapéldánkban egy nagyon egyszerű és teljesítmény szempontjából nagyon rossz webszervert fogunk írni, ami minden kérésre 404-et ad vissza. Annyit fog csinálni, hogy minden beérkező kapcsolatra forkol egyet, majd annak kiszolgálása után kilép. Mivel a fork egy erőforrás-igényes művelet, ezt élesben nem ajánlanám.
#!/usr/bin/php
<?php
declare(ticks = 1);
$parent = true;
$children = array();
pcntl_signal(SIGCLD, 'handle_child', true);
function handle_child($signo) {
global $children;
while (($pid = pcntl_wait($status, WNOHANG)) > 0) {
unset($children[$pid]);
}
}
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($sock, '127.0.0.1', 8081);
socket_listen($sock);
while ($parent) {
/**
* Blokkolva varakozzunk addig, amig nem kapcsolodik valaki.
*/
$client = socket_accept($sock);
$pid = pcntl_fork();
if ($pid == -1) {
/**
* Zarjuk be a kapcsolodo kliens socketet.
* Mivel nincs gyerek, ezert connection resetet fog kapni.
*/
socket_close($client);
} else if ($pid == 0) {
$parent = false;
$data = '';
/**
* Olvassunk addig, amig ket ujsort nem kapunk
*/
while (strpos($data, "\r\n\r\n") == false) {
$data .= socket_read($client, 1024);
}
/**
* Irjuk ki, hogy nem nyert.
*/
socket_write($client, "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nNot Found');
socket_close($client);
} else {
$children[$pid] = $pid;
/**
* A szuloben zarjuk be a kapcsolodo kliens socketet
*/
socket_close($client);
}
}
/**
* Zarjuk le a listen socketet.
*/
socket_close($sock);
És akkor most tessék szépen bepötyögni a böngészőbe: http://localhost:8081/, és lehet csodálkozni. Alig 5 perc alatt írtunk egy – igaz távolról sem tökéletes, de – webszerverként funkcionáló valamit.
Összegzés
Remélem, a fenti ízelítő jelleggel bemutatott technikákkal sikerült egy kicsit felkeltenem a szunnyadó érdeklődést a rendszer mélyebb rétegei iránt. Némi időráfordítással a PHP is nagyon hasznos háttérfeldolgozó nyelv és hasznos bajtárs tud lenni a nagy rendszerek adatfeldolgozásában.
Ha szeretnél még játszani a fentiekkel, akkor házi feladatnak próbáld meg a bemutatott technikákat egy jól működő HTTP szerverré összegyúrni. Esetleg írj róla cikket, kommentet.
■
Resource-ok
A resource-kezelés viselkedéséről érdemes lett volna írni még egy keveset, mert forkolás esetén az összes resource használatban marad a child és a parent processben is. Viszont, ha lezárjuk bármelyik processben a resource-t, akkor a másik processben is bezárásra kerül. Ezzel én főleg adatbáziskapcsolat-kezelés kapcsán találkoztam eddig.
C
Ez mennyit gyorsít?
Válaszolok is
Jogos kérdés
Ahol hasznos lehet még a párhuzamosítás az pl a migráció, amikor nem egy script tolja át egyik rendszerből az adatokat a másikba, hanem párhuzamosan több.
Ugyanilyen alkalmazási lehetőség, amikor egy háttérfolyamattal webfelületen keresztül kommunikál a felhasználó, csak ott egy további kommunikációs layert be kell tenni.
Nagy terhelésű rendszereknél előfordulhat, hogy bizonyos feladatokat egy queue-ba (activeMQ, gearman, stb.) tolunk be, és háttérfolyamatok végzik el azokat.
Nekem az utóbbi időben a favoritom a supervisord által felügyelt folyamatosan futó háttérfolyamatok, már ahol szükség van ilyesmire.
Is
Hogy rávilágítsak a módszer egy teljesen más előnyére, ha például socketen blokkolva várakozol és mindezt kombinálod a mostanában felkapott JavaScript long poll (COMET) megoldással, elég könnyen tudsz full realtime dolgokat írni. Természetesen nem azt mondom, hogy egy ActiveMQ-val szemben megállná a helyét de ez elég lightweight és hordozható, mindössze egy Unixon futó PHP kell hozzá.
PHP: jó étvágyat!
Tehát daemon írás a cronban ütemezett scriptek helyett, mindenképpen jó ötlet, de azt a lehető legnagyobb körültekintéssel tegye a PHP programozó. És főként ne felejtsük, hogy nem bűn a PHP mellett egy másik (daemon írásra alkalmasabb), nyelv elsajátítása.
+1
Ettől függetlenül természetesen lehet PHP-ban is ilyen szoftvereket írni csak kritikus szemmel kell nézni az alkalmazás mutatóit. Talán érdemes követni azt a talán nem egészen mérnöki kifinomultságnak megfelelő elvet, hogy a workerek időnként fejezzék be a működésüket és szülessenek helyettük új processzek (lásd: forkolós példa).
Mi a baj a crontabbal?
Rosszul skálázódik
Tegyunk tisztaba par
"Egy percnél finomabban nem tudsz időzíteni,"
Es ez miert gond? Mit szerettel volna idoziteni egy percnel surubb idotartamra?
"akkor is eszi a CPU-t ha nem csinál semmit,"
Erre bizonyitekot kerek. Valoban, a crond esz valami nagyon keves CPU-t, amikor fut, de az annyira keves, hogy meg az eppen belogott shelled is tobbet eszik nala.
"nem tud on demand reagálni"
Mert mondjuk nem feladata neki? A cron ugyanis arrol szol, hogy idozitve futtatunk valamit. Ez by definition zarja ki az on-demand reagalas lehetoseget.
"nagyon rosszul skálázódik."
Merrefele? Illetve miert is kellene skalazodnia? Szerintem definicios problema van itt is, de jobb lenne valaszokat hallani.
Nagyon nagy felreertesek vannak a crontab (pontosabban a cron altal idozitett feladatok) fogalmanak elkepzeleseben. Eredetileg ezt arra talaltak ki, hogy bizonyos feladatok elvegzesehez ne kelljen peldaul hajnali fel haromkor bejelentkezni es kezzel futtatni a parancsot, hanem ez automatikusan tortenjen meg. Ha ilyen feladat van, en rendszergazdakent jo szivvel biztatom a PHP programozokat a crontab hasznalatara, a hatterben futo php processz sokkal-sokkal tobb memoriat eszik varakozas kozben, mint az ilyen szempontbol optimalisabban megirt crond processz.
Johetnek a kovek.
Kövek. :)
Es ez miert gond? Mit szerettel volna idoziteni egy percnel surubb idotartamra?
Hasamra csapva: amikor domain lejáratnál versenyeznek az emberek a domainért nagyon nem mindegy, hogy egy másodpercen belül reagálsz a fölszabadulásra vagy egy percen belül.
Erre bizonyitekot kerek. Valoban, a crond esz valami nagyon keves CPU-t, amikor fut, de az annyira keves, hogy meg az eppen belogott shelled is tobbet eszik nala.
Valóban nem akkora szempont, de a percenként fölébredő majd egy adott esetben igen méretes táblából selectáló PHP script nem éppen kíméletes a géppel. Arról persze nem is beszélve hogy totál szekvenciálisan fog futni. (Ha meg nem akkor már eleve jobban jársz a daemonnal.)
Mert mondjuk nem feladata neki? A cron ugyanis arrol szol, hogy idozitve futtatunk valamit. Ez by definition zarja ki az on-demand reagalas lehetoseget.
Nem mondtam, hogy a crond bizonyos feladatokra nem megoldás, nagyon sok mindenre megoldás különben nem használnánk. De az nagyon sok butatót rejt amikor folyamatos háttérprocesszálás crondből fut.
Merrefele? Illetve miert is kellene skalazodnia? Szerintem definicios problema van itt is, de jobb lenne valaszokat hallani.
Pl értelmesen nem tudod két gépen összeszinkronizálni a futásukat. Nem mondom, hogy nem lehet megcsinálni de ahhoz azért nagyon kell tudni hogy ne legyen buktató benne.
Nyilván erre hülyeség daemont írni, de ha percenként futtatja valaki a PHP scriptjét akkor el kell gondolkozni a crond alkalmasságán.
Johetnek a kovek. Beallnek en
Beallnek en is a sorba.
Egyreszt ugye megvan a cronnak a sajat szerepe, van amire nagyon jol hasznalhato.
Masreszt, viszont tegye fel a kezet, aki meg nem jart ugy, hogy:
- cronjobok egymasrafutottak, mert az egyik beakadt/tul lassan futott le, es rafutott a kovetkezo.
- volt valami typo a crontab bejegyzesben (pl. egy hianyzo ujsor a fajl vegerol) es kurva maceras volt debugolni.
- website koltoztetes soran elfelejtette a rendszergazda atvinni a crontab bejegyzeseket az uj szerverre (vagy azert mert nem masolta at az /etc/cron.d konyvtarat, vagy azert, mert crontab -e -vel lett felveve, es a /var/spool/cron/crontabs/ atmasolasa maradt ki)
Persze ha naponta 1szer, mondjuk ejfelkor ki akarod purgalni az inaktiv usereket a db-dbol, vagy havonta egyszer ki akarsz kuldeni egy ertesitot a hirleveledre feliratkozott usereidnek, akkor arra a cron a legjobb megoldas.
De ha tobb procit akarsz kihasznalni(tobb peldanyban akarod futtatni a taskot), esetleg interaktiv modon (itt azt ertem, hogy ha van melo akkor folyamatosan, megszakitas nelkul dolgozik, ha nincs mit csinalni, akkor meg nem eszik cpu idot) pollolgatas nelkul, akkor valoszinuleg nem a cronra van szukseged.
btw: proclub, emlekszel, hogy mondtam anno, hogy szukseg lenne/lesz a crontab vs daemon kerdeskorben egy magyarazatra, hogy mik az elonyok hatranyok, es mikor melyiket hasznaljuk?
valahogy sejtettem, hogy lesznek olyanok, akiknek nem lesz vilagos, hogy melyiket mire erdemes hasznalni, es hogy egyik sem jobb a masiknak, hanem eltero igenyekre kinalnak nemi atfedessel megoldast.
Tyrael
Kipróbálta valaki?
en csak most neztem ra
jonak tunik, de az umask(0)-t kihagytad a daemonizalas lepesei kozul (meg persze el lehetne valtani a working dir-t, de akkor meg az kell irni egy normalis autoloadert)
Tyrael
Működik
Egy kényelmetlen dolog van egy ilyen fejlesztésnél: vigyázni kell, hogy fork előtt ne legyen semmilyen erőforrás megnyitva (pl.: adatbázis kapcsolat, fájl leíró) mert a fork-nál ez másolódik, és ettől az adatbáziszerver nagyon megzavarodik. Fork előtt mindig be kell ezeket zárni, ha volt nyitva, adatbázishoz kapcsolódni meg mindig fork után kell.
Jo cikk, de en meg emlekszem
Valóban
Egy ideje nézegetem a Pythont és minél többet nézem, annál jobban kezd tetszeni. Ma pl fél óra alatt írtam egy daemont ami chrootol, uidot vált, lecsatlakozik a terminálról és socket szervert indít. Mindezt úgy, hogy gugliznom is kellett utána. Ha elég jártasságot szerzek benne valszeg lesz belőle cikk.
Python
Scriptelek
Akkor nezd meg a ruby-t is.
Nem jött be
http://www.sinatrarb.com/ sas
sasold meg, nekem rajta van a todo listan, de elegge hatul.
amugy van meg par rubys keretrendszer, de nekem ez volt a ror mellett a legszimpatikusabb.
Tyrael
Python
(Most olyan feladatok vannak mint realtime logelemzés LDAP lookuppal. A Perl és a PHP már elvérzett.)
bar nem kellett meg soha
Tyrael
CPAN
A PHP-s működik, bár nem ekkora adatmennyiséggel próbáltam.
Thread-kezelés
nem egeszen igy van. maga a
maga a php thread safe, viszont nem mindegyik modul az.
windows alatt kevesebb a nem thread safe module, ezert ott kissebb az eselye, hogy talalkozol a problemaval.
a php manualban is kb. ez szerepel:
http://www.php.net/manual/en/faq.installation.php#faq.installation.apache2
amennyiben nem mpm kornyezetben hasznalod, akkor erdemes az nts verziot felrakni, mert gyorsabb.
Tyrael
Szép
A fentieket egyik saját projektünk esetében már közel 4 éve alkalmazzuk egy mission-kritikus rendszer esetében, különösebb problémák (segfaultok, leakek) nélkül, én tehát nyugodt szívvel merem ajánlani.
További jó anyag a témában a sokat ismételgetett PHP5 felsőfokon című könyv, amiben egy külön fejezetet szentel a démonok írásának, foglalkozva azzal az igen fontos kérdéssel, hogy egy "tisztességes szülő folyamat feladata, hogy eltakarítson a gyermekei után".
Egy jópofa folytatásként eszembe jutott az is, hogy némi továbbfejlesztéssel ki lehetne alakítani egy egyszerű map-reduce rendszert feladatok partícionálására és párhuzamos, asszinkron végrehajtására, a'la Google. A Master lehetne a szülőfolyamat, amely a worker-eket hoz létre (forkol), de minimális továbbfejlesztéssel akár a workerek is lehetnének önálló démonok, és így relatíve egyszerűen kiterjeszthető lenne több gépre is a koncepció. De jó lenne erről egy cikk... :)
Párhuzamos feldolgozás
Kötelező olvasmány
Kicsit úgy érzem magam, hogy kinyitottam egy könyvet egy olyan témáról, amit az életben nem hallottam, és nincs hozzá tartalomjegyzék, vagy vázlatos leírás.
Lehet, hogy egyedül vagyok vele, de én úgy érzem, hogy az előző cikk nekem, mint egy témában járatlan embernek kevés volt. Vannak olyan alapfogalmak, mint process meg signal, amiket nem tisztáztál a cikksorozat elején. Persze azt is elfogadom válaszul, hogy nem akarsz leereszkedni a hülyék szinjére. :-D
http://en.wikipedia.org/wiki/
innen elindulsz, koveted a linkeket es rendben leszel.
Tyrael
Sok idő kell hozzá...
hazat epiteni az alapoktol
nem varhato el minden cikkirotol, hogy a hogyan epitsunk cassandra clustert jellegu irasokban a linux telepitesenek es configuralasanak a lepeseivel kezdje a bevezetot.
Tyrael
Nyilván
Kösz :-)
ez ilyen. Tyrael
szerk:
ezt ide akartam irni:
http://weblabor.hu/cikkek/nagy-terhelesu-rendszerek-fejlesztese-2#comment-68568
Tyrael
Én épp most fejeztem be egy
nohup
Köszönetet
Tesztelésre nagyon hasznos!
Üdv:
Gábor